arrays 🔗

Instructions

This workshop aims to check your understanding.

Each task will explain whether or not you should run the code.

For each task, you can use JS2 week 1 prep
to help you with the questions.
You can also use documentation to look up any functions that are unfamiliar.
Don’t use ChatGPT or any other AI tool to help you.

🧰 Setup

  1. Get into pairs or groups of up to three.
  2. Make sure you have a clone of the CYF-Workshops repository on your local machine

This workshop can be found here 👉 https://github.com/CodeYourFuture/CYF-Workshops/tree/main/arrays
In this workshop, each file contains a different problem at a particular level.

You should start this project at Level 100 and then move through the levels in ascending order, level 200, 300 etc.

➡️ Go to Level 100

asking-questions 🔗

Asking Questions 101

Prep

Today we’re going to start learning a formal language of developer questions. We will begin with this basic format:

  1. What I did
  2. What I expected
  3. What actually happened

This format helps to find the discrepancies between expectations and reality. (This is the gap in our understanding.)

It’s also an efficient way to share our current understanding with others.

Expectation vs reality

When we are surprised by an outcome it usually means we had a mental model of the world that didn’t predict the world accurately. Don’t panic when this happens, it’s completely expected for even experienced developers to run into surprises. We use these gaps as signs that we need to update our mental models.

To develop our understanding of coding, we will:

Predict & Explain

  1. Make a prediction by explaining what the outcome will be
  2. Play computer - “run” the model in our heads and predict (say before) what the outcome will be

Try

  1. Code up our idea
  2. Run the code

Compare and Update

  1. Compare the outcome with our prediction
  2. Explain the gap between our prediction and what actually happened
  3. Update our understanding

This process is cyclical.

graph LR A[Predict] B[Explain] C[Try] D[Compare] E[Update] A --> B B --> C C --> D D --> E E --> A

Updating the right model

If you stuck and can’t explain the gap in your mental model, then it’s time to ask a question!

When we ask questions, it’s important that we share our current mental model as part of your question so that other people can test the right thing, focus on the mis-understanding. Then together you can get quickly to a shared understanding of your specific problem.

Let’s look at how asking questions helps you update your mental model with an example.

Inversion, 5m

  1. Set a timer for 5 minutes.
  2. Popcorn around the room and each person give an example of a bad way to ask a question until the timer goes off. For example:

Argh I can’t make it work please help me!

Why are these not useful?

Inversion 2, 10m

  1. Set a timer for 10 minutes.
  2. Popcorn around the room and each person give a reason the previous question was bad until the timer goes off. For example:

What is it? What are you trying to do? In what way is it not working? Be specific! Share what you see. Do you have a link? What do you want it to do?

Exercise ground rules

Before we get to the next exercise, let’s just set some ground rules here:

  1. The goal is not to complete the exercise; the goal is to learn
  2. The smart thing to do is to focus on the questions you cannot (yet) answer

Framing questions systematically, 30m

Split into groups of 2-5 people.
Set a whole class timer for 30 minutes.

Confound yourselves

  • Pick a problem from the bank.
  • As a group, make a prediction about what you think the answer is, and write it down.
  • Test your prediction. Try it out using the dev tools.
  • Compare your prediction with the outcome.

What happened? Is there a gap in your understanding?

Keep doing this until you find a problem you can’t solve, then write up your mental model using this format:

  1. What I did
  2. What I expected. Make sure you include your prediction here
  3. What actually happened

Include as much context as you can, including links, line numbers, sample code, etc. Use code blocks to mark up your code. If you use screenshots, they should only show the visual render (never screenshot code - paste code as text).

Now post your write up of the question in #cyf-ask-tech-stuff.

🧑🏾‍💻🙋 Developer questions contain

  1. 🔗 Links 👍
  2. Objectives - what are you actually trying to do? 👍
  3. 🖼️ Screenshots of UI 👍
  4. 📝 Code blocks 👍
  5. 📷 Screenshots of code 🙅

📚 Further reading

breakdown 🔗

Break it down

https://www.whatshalfway.com/

Here is an app that helps users find a halfway point to meet up.

How does this work?

How would you build this in real life?

You have probably done lots of tutorials where you follow along and copy what the teacher shows you, and this does teach you some simple things about programming. But it doesn’t teach you how to solve your own problems or build your own products, and it doesn’t help you when things go wrong. To understand how to develop really new things, you have to practice thinking up your own solutions and trying (and failing a lot).

So let’s start today by “reverse engineering” an existing app together.

Start by identifying the core functionality of this app. Forget about the web page, or the fonts, or the name… what does this thing REALLY DO? What is the simplest version of that function you can build and test.

Split into groups of 4-6. Choose one of the group to wear the User Hat. If in doubt, blocked, or making an assumption, ask the User what to do.

User Stories

Spike on User Stories, 10m

  1. Set a timer for 10 minutes.
  2. Define a User Story:
    “As a user, I want to do x so that I can y.”
Perhaps you said something like...
  • As a user, I want to draw a line and cut it in half.
  • As a user, I want to find the midpoint between me and my friend so we can meet for lunch.
  • As a user, I want to enter two different locations and receive information about the geographic midpoint between them.

Put all your user stories together and vote on the best one. Now let’s spike on Acceptance Criteria.

Acceptance Criteria

Spike on Acceptance Criteria, 10m

  1. Set a timer for 10 minutes.

  2. Define Acceptance Criteria (Given/When/Then):

    Given some scenario, when I do something, then I expect some outcome.

Perhaps you said something like...
  • Given that I have two distinct geographical locations,
  • When I input these locations into the application,
  • Then I should be provided with the geographic midpoint between the two locations.

Put all your acceptance criteria together and vote on the best one. Now we understand it more clearly, let’s spike on a test for this feature.

Test

Spike on Test, 15m

  1. Set a timer for 15 minutes.
  2. Define a test: - What is the simplest test you can write to prove that your acceptance criteria is met? - What is the simplest code you can write to pass that test?
Perhaps you said something like...
const calculateMidpoint = require("./calculateMidpoint");

test("calculateMidpoint calculates the correct midpoint", () => {
  expect(calculateMidpoint(51.5074, 0.1278, 48.8566, 2.3522)).toEqual({
    lat: 50.182,
    lon: 1.24,
  });
});

This test defines two locations, London and Paris, and expects the midpoint between them to be calculated to three decimal places.

You might not have chosen to use longitude and latitude at all, so your test might look different. That’s ok! The important thing is that you have a test for the acceptance criteria you defined.


Now that we have a test, we can write the simplest code to pass that test.

Code

Spike on Code, 15m

  1. Set a timer for 15 minutes.
  2. Write the simplest code to pass your test.
Perhaps you said something like...
function calculateMidpoint(lat1, lon1, lat2, lon2) {
  // Compute average latitude and longitude
  const mid_lat = (lat1 + lat2) / 2;
  const mid_lon = (lon1 + lon2) / 2;

  return {
    lat: parseFloat(mid_lat.toFixed(3)),
    lon: parseFloat(mid_lon.toFixed(2)),
  };
}

module.exports = calculateMidpoint;

This code takes two locations, calculates the average latitude and longitude, and returns the midpoint between them, more or less. It’s more complicated to calculate the midpoint between two points on a sphere accurately.

So we have discovered something we need to ask our user about:

how accurate do you need this to be?

Remember we are writing the simplest thing that can possibly work. For now, we’ll use this rough calculation.


OK that’s a spike! We have a test and some code that passes that test. We can go forward and build this app for the rest of the day if we like. But first, let’s do it again with a different product.

Practice makes permanent

Go to the CYF Product Factory and get a random product. Break it down into user stories, acceptance criteria, tests, and code.

  1. Discover the core functionality of the product.
  2. Write a user story for that functionality.
  3. Write acceptance criteria for that user story.
  4. Write a test for that acceptance criteria.
  5. Write code to pass that test.

components-1 🔗

First Components

Today we’re going to think about components. We’re going to build a page using a design system and we’re going to collaborate on a feature branch workflow.

The overall mission is to compose “components” / groupings of HTML elements to re-build this web page: CYF Components Workshop.

Learning Objectives

Requirements

Before you start, make sure you’ve installed the CYF Extension Pack in VS Code.

npm install -g prettier

Set up your feature branch 15m

Set up your feature branches

Divide the class into three teams: header, footer, card. Use the team generator to help you do this.

Set a whole class timer for 10 minutes.

Each team, choose a driver

  1. Driver, clone this repository
  2. Driver, create and checkout a new branch for your team named like this: feature/cohort-component, where cohort is your cohort name and component is the component you’re building, for example: feature/nw6-header
git switch --create feature/cohort-component

Now you’re all set up to make changes to together.html.

Find your docs 10m

Find your docs

Set a whole class timer for 10 minutes.

Deployed from this repo is a mini design system. This design system has several documented components: card, header, and footer. Each component view has some sample code and some statements about the components.

Your mission is to find the docs for your component and read them.

Together separately

Set a whole class timer for 30 minutes.

Parallel Development 30m

Now build your component. Elect a new driver.

  1. Find together.html in the /components-1 directory. Your mission is to complete this page.
  2. In the correct portion of the page, make your changes to build your feature on together.html.
  3. Driver, commit your changes to your feature branch.
  4. Open a pull request from your branch to main, with your changes.
  5. Remember, docs will help you.
  6. Do the simplest thing that could possibly work to begin with. You can always update your PR with more changes.
gitGraph commit id: "start" branch feature/cohort-component commit id: "paste html from docs" commit id: "fill in the blanks" commit id: "lighthouse revisions" checkout main merge feature/cohort-component

Review and merge

Now we’re going to review each other’s work. If a mentor is available, they can be the driver for this part and you can actually merge your PRs. If not, please don’t try to merge as you could make a mess of this shared repo.

Note to mentor: please revert together.html to the initial commit after you’re done so the next class can use it. (Or if your group has time for it, you can merge on a fork instead.)

Set a whole class timer for 30 minutes.

Review 30m

  1. Go to the pull requests for this repo.
  2. Either individually or as a group, review each other’s PRs.
  3. Once you’re all happy with the PR, merge it.
  4. Did it work? Why/why not? Discuss.

Acceptance Criteria

  • We have worked in three teams to build a page using a design system
  • We have used a feature branch workflow to collaborate
  • We have reviewed each team’s PR

components-2 🔗

Components are Functions

Today we’re going to think some more about components. We’re going to build a page using a design system and we’re going to collaborate on a sub branch, feature branch workflow. We’re going to identify the difference between HTML and the DOM using Devtools. And we’re going to create new DOM nodes using JavaScript functions. Oh my goodness, it’s so many things! That’s why it’s best to do this workshop after you’ve done:

And in particular, these workshops:

If you missed these workshops in your cohort, it’s a good idea to try to do them in the week (online) first. Record your session for people that can’t attend. Everyone should try to do the workshops first, either in groups or solo if necessary.

The overall mission is to compose “components” / groupings of HTML elements to build a page in together.html.

But this time, we’re going to use JavaScript functions to build our components.

Learning Objectives

Set up your working branch 15m

Set up your working branch

Everyone should do this so everyone is set up correctly.

  1. You will be working on a special branch called FOR-USE-IN-CLASS.
  2. First, clone the workshops repository
    Checkout git switch FOR-USE-IN-CLASS
  3. Your cohort has a named sub branch. Everyone, check that out next with git switch --create COHORT (eg NW6). This is your working branch.

Check you are in the right place with GitLens!

Visualise this Git workflow

gitGraph commit "main" branch FOR-USE-IN-CLASS checkout FOR-USE-IN-CLASS branch NW6 checkout NW6 branch feature/header commit commit checkout NW6 branch feature/footer commit commit commit checkout NW6 branch feature/card commit commit commit checkout NW6 branch feature/menu commit commit commit checkout NW6 merge feature/header merge feature/footer merge feature/card merge feature/menu

Your working branch is your cohort name

Your COHORT branch is your cohort name. It might be NW6, WM5, GL7… You’ll be making branches starting from your COHORT branch and NOT starting from main.

Get set up to work in teams

Next, divide the class into four teams: header, footer, card, menu. Use the team generator to help you do this.

Set a whole class timer for 10 minutes.

Set up your branch 10m

Each team, choose a driver

  1. Driver, ask everyone in your team to confirm you are in the right working branch.
  2. Driver, from this branch, create and checkout a new branch for your team named like this: feature/cohort-component, where cohort is your cohort name and component is the component you’re building, for example: feature/nw6-header
git switch --create feature/cohort-component

Now you’re all set up to make changes to together.html.

Find your docs

Set a whole class timer for 10 minutes.

Find your docs 10m

Deployed from this repo is a mini design system. This design system has several documented components, and some also have JavaScript files.

Your mission is to find the docs for each component with an associated script file, and read them. Discuss your findings. Here are some things to consider:

Look at the pages on the website with Devtools. Compare the Inspect view with the source code you can see in the files. How are they different? How are HTML and the DOM different?

What is a module? What does this code do <script type="module">import Header from "./docs/header/header.js";</script> ?

Together separately

Set a whole class timer for 30 minutes.

Parallel Development 30m

Now build your component. Elect a new driver.

  1. Find together.html in the /components-2 directory. Your mission is to complete this page.
  2. In the correct portion of the page, make your changes to build your feature on together.html.
  3. Driver, commit your changes to your feature branch.
  4. Open a pull request from your branch to the COHORT branch, with your changes. Ask for help!
  5. Remember, docs will help you too.
  6. Do the simplest thing that could possibly work to begin with. You can always update your PR with more changes.

Review and merge

Now we’re going to review each other’s work and merge to our cohort branch.

Your COHORT branch is your cohort name. You’re working in your COHORT branch and not in main. Open your pull request to your COHORT branch.

Your working branch is your cohort name

Don’t open PRs to main. If you do open a PR to main and it is merged then it would break the exercise for other trainees.

Visualise this Git workflow

gitGraph commit id: "start" branch FOR-USE-IN-CLASS branch COHORT branch feature/component commit id: "import component function" commit id: "import data" commit id: "lighthouse revisions" checkout COHORT merge feature/component

Set a whole class timer for 20 minutes.

Review 20m

  1. Go to the pull requests for this repo.
  2. Either individually or as a group, review each other’s PRs.
  3. Once you’re all happy with the PR, merge it.
  4. Did it work? Why/why not? What does “work” mean for this workshop? Discuss.

Acceptance Criteria

  • We have worked in teams to build a page using JavaScript components and modules
  • We have used an advanced sub-branch feature branch workflow to collaborate
  • We have reviewed each team’s PR

crud 🔗

CRUD 101

Learning Objectives

Requirements

Today we will build a CRUD API. CRUD stands for Create, Retrieve,* U*pdate, Delete. If you think about it, this is what most applications do:

Create some “resources”
Retrieve them (GET them)
Update them
Delete them

🎯 Workshop Objective

Our API will manage Beyoncé albums. It will:

Create a new album,
Retrieve a list of albums or a single album,
Update an existing album’s information
Delete an album

We will build these endpoints:

  1. GET /albums should return all the albums
  2. GET /albums/:albumId should return a single album (that matches the passed albumId)
  3. POST /albums should save a new album
  4. DELETE /albums/:albumId should delete the album (that matches the passed albumId)

1. GET /albums should return all the albums

In server.js, create a GET /albums endpoint that returns all the albums. Some albums have been provided for you in albums.json.

app.get("/albums", (req, res) => {
  res.send(albumsData);
});

🧪 Run and test

  1. npm run dev
  2. Open Postman
  3. Make a GET request to http://localhost:3000/albums

2. GET /albums/:albumId should return a single album (that matches the passed albumId)

Sometimes, we do not want to list all the information in one request, maybe we only want to get the information related to a single album. Imagine if we have a page to display the details of one album. We could call the server and get all albums then filter the one we need client-side. It would be more effective to tell the server to just return the one album we are interested in.

We will now add a new endpoint to return only a single album GET /albums/:albumId. In this case, albumId will tell us what album we can return. The call will be GET /albums/10 and that will return the album with that has albumId: "10".

This endpoint has something different. The endpoint /albums/:albumId has a dynamic part. The albumId will vary depending on what the client sends.

In server.js, create a GET /albums/:albumId endpoint that returns a single album. The albumId will be passed as a parameter in the URL.

app.get("/albums/:albumId", (req, res) => {
  const albumId = req.params.albumId;
 // now find the given album from the `albumsData` using the `albumId`
 // finally send the album you found back to the client
});

🧪 Run and test

  1. Save your changes
  2. Make a GET request to http://localhost:3000/albums/10
  3. Try changing the id in the URL and calling the endpoint again. What do you see?

3. POST /albums should save a new album

In order for our server-side to receive and use the data sent by the client, we will need to install and use a middleware.

The JSON middleware makes it easy for our route handlers to read JSON data from the request. If the Content-Type request header indicates that the request body contains JSON data then the middleware calls JSON.parse to convert the request body into a JavaScript data structure.

To register the JSON middleware, add the following to the server code:

app.use(express.json()); // before our routes definition

In server.js, create a POST /albums endpoint that saves a new album. The album will be passed as a JSON object in the request body.

Step by step if you get stuck
  1. Add the following code to server.js:
app.post("/albums", function (req, res) {
  const newAlbum = req.body;
  albumsData.push(newAlbum);
  res.send("Album added successfully!");
});
  1. Open Postman and create a new request.
  2. Set the Request Type to POST.
  3. Enter the URL for your endpoint, which should be http://localhost:3000/albums.
  4. Set the Body Type to raw and format to JSON (application/json).
  5. Enter the Album Data in the body of the request as JSON:
{
  "albumId": "13",
  "artistName": "Beyoncé",
  "collectionName": "B'Day (Deluxe Edition)",
  "artworkUrl100": "http://is5.mzstatic.com/image/thumb/Music/v4/6c/fc/6a/6cfc6a13-0633-f96b-9d72-cf56774beb4b/source/100x100bb.jpg",
  "releaseDate": "2007-05-29T07:00:00Z",
  "primaryGenreName": "Pop",
  "url": "https://www.youtube.com/embed/RQ9BWndKEgs?rel=0&controls=0&showinfo=0"
}
  1. Click Send.
  2. You should see the album you just created in the response.

4. DELETE /albums/:albumId should delete the album (that matches the passed albumId)

This means that DELETE /albums/2 should delete an album with the id 2 and return 200 with JSON { success: true } to the user.

The code will look like this

// notice .delete
app.delete("/albums/:albumID", function (req, res) {
  console.log("DELETE /albums route");
});

Can you work out how to remove an album using this code?

Acceptance Criteria

  • I have written a server that can handle the following requests:
    • GET /albums
    • GET /albums/:albumId
    • POST /albums
    • DELETE /albums/:albumId
  • I have used Postman to test my server

Resources

dad-joke 🔗

Joke Fetcher App

This simple app fetches jokes from an API and displays them. Here are some ways we could improve it:

Acceptance criteria

  1. Given a Joke API
    When the page first loads
    Then a random joke will be displayed on the page
  1. Given a joke has already been fetched and displayed
    When the user clicks the “Get New Joke” button
    Then a new random joke will be fetched and replace the existing one
  1. Given there is a slow network
    When the page first loads
    Then a loading message will be displayed…

🐛 Debug

❗ Commit after completing each task ❗

  1. Separate code into separate files - HTML, JS, CSS
  2. Fix functionality for acceptance criterion 1 only

Navigator:

  • Describe out loud the current behaviour in the user interface
  • Describe what you should expect to see given the acceptance criterion
  • Step through the code to make sense of where the bug is coming from
  1. Fix functionality for acceptance criterion 2 only

Navigator:

  • Describe out loud the current behaviour in the user interface
  • Describe what you should expect to see given the acceptance criterion
  • Step through the code to make sense of where the bug is coming from
  1. Check all acceptance criteria are working ( including 3 )

Refactor 🧹

  1. Refactor getJokes to use async/await

Challenge 💪

  1. Try implementing a loading spinner using CSS

db-backup 🔗

Development environment and database Workshop ⚙️

This workshop will guide you through the following:

  • setting up your development environment
  • initialising a local database
  • removing, re-initializing, and most importantly, backing up your database for the Full Stack Product.

Learning Objectives

Requirements

  • Check you’ve split into a team for the Full Stack Project
  • Clone your team’s fork of the Full Stack Project Assessment repository to your local machine.
  • Locate the User story: Video recommendation listing issue on the Project Kanban board
  • From the User story: Video recommendation listing issue, locate the Setup your local development environment and Setup your local database issues
  • Have a code editor or terminal ready.

Part 1 - Set up your local development environment

  • Set a whole class timer for 10 mins ⏱️
  • Follow the instructions in the setup guide to set up your local development environment
  • Check the acceptance criteria on the Setup your local development environment issue. Has everyone in your team met the acceptance criteria for this issue?

Part 2 - Set up your local database

  • Set a whole class timer for 15 mins ⏱️
  • Use the instructions for the db setup guide to set up a local database with one table and some data. Use the first section in the instructions to complete this task.
  • Check the acceptance criteria on the Setup your local database issue. Which criteria have you met?

Part 3 - Backup your local database

  • Set a whole class timer for 15 mins ⏱️
  • Use the instructions for the db setup guide to backup your local database
  • Check the acceptance criteria on the Setup your local database issue. Which criteria have you met?

Part 4 - Remove, Re-store, and Restoring

  • Set a whole class timer for 15 mins ⏱️
  • Use the instructions for the db setup guide to backup your local database
  • Check the acceptance criteria on the Setup your local database issue. Which criteria have you met?

Practice Makes Perfect

Set another timer and repeat the dropping, re-initializing, and restoring process a few more times to solidify your understanding. Experiment with different backup file locations if you’d like.

By the end of this workshop, you should feel confident in creating, removing, re-initializing, and backing up your database so you don’t need to worry about losing your data.

Acceptance Criteria

Double-check the acceptance criteria on the issues: Setup your local development environment and Setup your local database

By completing these steps, you’ve mastered the fundamentals of database setup for the Full Stack Assessment, and you’re ready to tackle the next challenge!

debugging-2 🔗

Debugging workshop - 2

Please follow the steps below:

  1. The class should split up into seperate breakout rooms.
  2. Each team should check debug_checklist.md file first and discuss which other strategies they would consider for debugging codes.
  3. Instructors will pick up one of the team’s checklist and do a demo for levels 100 and 200 in front of the whole group.
  4. Trainees go back to their breakout rooms and debug level 300 in their teams.

debugging-3 🔗

Debugging Part 3: React Components

Install

In the project directory, you can run:

npm install

Start

In the project directory, you can run:

npm start

Tasks

In the folder features you will find a bunch of files that relate to the functionality of the different components. For each of the features you
must read the scenario and fix/implement the required behavior

Goal

The goal here is to focus on fixing one small part functionality at a time. Trainees should:

  • fix one scenario
  • test it works
  • commit the changes

debugging 🔗

Debugging is Asking Questions

Prep

Whew, that’s loads! But we did set it all as coursework, so you have done it already, right? 😉

Today we’re going to use our formal language of developer questions. We began with this basic format:

  1. What I did
  2. What I expected
  3. What actually happened

This format helps to find the discrepancies between expectations and reality. (This is the gap in our understanding.)

It really helps us with debugging. Today we will use a debugger and our scientific method to find and fix bugs. Recall your scientific method:

Recap asking questions

Predict & Explain

  1. Make a prediction by explaining what the outcome will be

Test

  1. Run the code to see what actually happens

Compare and Update

  1. Compare the outcome with our prediction
  2. Explain the gap between our prediction and what actually happened
  3. Update our understanding

This process is cyclical.

graph LR A[Predict] B[Explain] C[Test] D[Compare] E[Update] A --> B B --> C C --> D D --> E E --> A

Setup

Get into pairs. Each pair consists of two roles:

  1. Computer: Execute the code mentally, predicting the outcome.
  2. Debugger: Use the VSCode debugger to step through the code.

You will swap roles after each exercise.

Set a whole class timer for 10 minutes.


          https://code.visualstudio.com/docs/editor/debugging

Stepping

Understanding Variables and Flow, 10m

Identify the value of variables at each step in a loop.

const sumArray = (numbers) => {
  let total = 0;
  for (let i = 0; i < numbers.length; i++) {
    total += numbers[i];
  }
  return total;
};
console.log(sumArray([1, 2, 3]));

Computer:

  1. Write down predictions for total and i values before each loop iteration.
  2. Compare predictions after each Debugger’s step.

Debugger:

  1. Open sumArray.js in VSCode.
  2. Choose ‘Run > Start Debugging’ from the menu.
  3. Set a breakpoint at total += numbers[i];.
  4. Step into your function.
  5. Step Over through iteration until your loop is complete.
  6. Monitor total and i in the Variables section.

Debugging

Okay, swap roles. Set a whole class timer for 15 minutes.

Finding an Error, 15m

const findLargest = (numbers) => {
  let largest = numbers[0];
  for (let i = 1; i < numbers.length; i++) {
    if (numbers[i] > largest) {
      largest = numbers[i];
    }
  }
  return largest;
};
console.log(findLargest([3, 7, 2, 5, 6]));

Debugger:

  1. Open findLargest in VSCode.
  2. Predict the return value of findLargest. Write your prediction down.
  3. Set a breakpoint at if (numbers[i] > largest).
  4. Debug and inspect i, numbers[i], and largest.
  5. Write down the return value of findLargest([3, 7, 2, 5, 6]).

Computer:

  1. Predict the value of largest after each loop iteration.
  2. ‘Execute’ the code and write down the actual value of largest after each loop iteration.
  3. Write down the return value of findLargest([3, 7, 2, 5, 6]).
  4. Now execute the code in VSCode. Did you get the same result?

Both (briefly) write up your mental model using this format:

  1. What I did
  2. What I expected. Make sure you include your prediction here
  3. What actually happened

Okay, swap roles. If you have time left and you’re into this, there are many problems stored in debugging/bank. Set a whole class timer for 15 minutes.

Problem Bank, 30m

Pick any problem from the bank and work through it together. Use the debugger and the scientific method to find and fix the bug.

Write up your findings in the developer question format. Swap roles and repeat until we run out of time.

🧑🏾‍💻🙋 Developer questions contain
  1. 🔗 Links 👍
  2. Objectives - what are you actually trying to do? 👍
  3. 🖼️ Screenshots of UI 👍
  4. 📝 Code blocks 👍
  5. 📷 Screenshots of code 🙅

📚 Further reading

devtools 🔗

Inspector Gadget

Prep

For this workshop you will need:

You’ve already used a little bit of Devtools in ITD when you used Lighthouse to audit your code. But there’s much much more! Devtools is an entire IDE (Integrated Development Environment) running inside your browser and it has hundreds of ways to inspect, test, and develop your code.

Explore

Each browser has its own Devtools. Download Safari, Chrome Canary, and Firefox Developer Edition to explore the differences.

Inspect the DOM

Explore

In groups of no more than five.
Take it in turns to swap the driver for each section of this workshop

  1. Set a whole class timer for 10 minutes.

  2. Inspect the page with Devtools.

  3. Write down the answers to these questions:

    • What is the name of the font used on the page?
    • What is the CSS variable that holds this value? (Hint: variables start with --, like, --paper)
    • What is the brand colour value (Hint: it’s set in a variable)?
    • What is the brand colour value used for in the page?
    • What variables hold CSS length data type values?
  4. When the timer goes off, share your answers with the other groups. Paste them in a thread in Slack and go quickly to the next challenge.

So we’ve seen that fonts, colors, and spacing are often stored as CSS Variables, or custom properties. This allows them to be easily changed throughout a project by simply altering one value. Let’s experiment with this.

Experiment

  1. Set a whole class timer for 10 minutes.
  2. Inspect the CSS of the page with Devtools.
  3. Find the CSS Variables (hint: variables start with --, for example, --paper)
  4. Try changing the values of these variables and see how it affects the page.
  5. Some questions to answer. (Make a prediction about what you think will happen first, and then test it)
  • What will happen when you click the value of --finger and press up arrow ten times?
  • What will happen when you delete the value of --copy
  • What will happen when you change the value of --space to red?

Reflection

When the timer goes off, set a new timer for 10 minutes to share your answers with the other groups.

Grid Inspector

Next, let’s see how the page layout is handled. Modern websites use the CSS Grid for layout and you can manipulate grids with Devtools.

Grid Editor

  1. Set a whole class timer for 10 minutes.
  2. With Devtools, locate a grid element on the workshop page.
  3. Activate the Grid Badge in the Elements panel.
  4. Use the Grid Editor to try changing the layout.
  5. Go straight to the next challenge!

Lighthouse

It’s important that software works and that people can use it. Lighthouse can help you write code correctly by pointing out your errors. But even better, it can teach you to fix the errors.

Audit

  1. Set a whole class timer for 10 minutes.
  2. Run a Lighthouse audit on the workshop page.
  3. Look at the results and identify the issue.
  4. Now, how will you fix it? Click on the error. Lighthouse explains what is wrong and provides a link to a detailed explanation on why it’s wrong, how serious it is, and how to fix it!
  5. If you have time, fix the error, but in any case, once the timer goes off, paste the link to the detailed explanation page into the workshop thread in Slack.
  6. Go straight to the next challenge, after which we will spend some time discussing what we discovered.

Hover for more

In fact Devtools is a great teacher. In the Styles panel, hover over any CSS property to get a quick definition of that property. Click ‘Learn More’ to go straight to the MDN page for that property.

If the explanation doesn’t make sense to you, ask ChatGPT (a generative AI) to explain it further.

Plausible Hallucinations

Remember: Generative AIs are regularly confidently wrong; it can be helpful, but never trust it over Devtools.

If something doesn’t make sense, or seems confusing or maybe wrong, it’s better to ask friendly humans in Slack.

Explore and Explain

  1. Set a timer for 10 minutes.
  2. Select <main> in the Elements panel
  3. Hover over the ruleset attached to main in the Styles panel.
  4. Copy the Devtools explanation and ask ChatGPT to explain it, like this:
Please explain this to me like I'm a beginner learning HTML and CSS.

Determine a grid item’s size and location within the grid by contributing a line, a span, or nothing (automatic) to its grid placement. Shorthand for ‘grid-row-start’, ‘grid-column-start’, ‘grid-row-end’, and ‘grid-column-end’.

  1. Come back together as a large group.

Reflect

Reflect

  1. Set a timer for 5 minutes.
  2. Spend five minutes discussing what you will share with the rest of the class about your experiments so far. What was a surprise to you? What will you use regularly from now on? What confused you? Elect one person to represent your group.
  3. Set a timer for 20 minutes.
  4. Popcorn round the representatives and share your findings. We’re not done yet so keep to time.

Many ways of examining the same thing

So we’ve explored the Elements panel, the Styles panel, and the Lighthouse panel. There are many many more panels, and they all expose a different way of interpreting, interacting with, or understanding the same code. Computer systems frequently do this. It’s a mistake to think that the way you use a website is the only way it can be used. Bots, crawlers, screenreaders, integrations…there are many and various consumers of your code, so it’s important to make sure you construct it properly.

For example, you have just looked in the Elements panel. This is not really your HTML, this is the DOM, an API the browser builds using your HTML. An example of how the DOM is different from HTML is that JavaScript can change what’s in the page - this changes the DOM, but doesn’t change the actual HTML. The DOM isn’t the only API it builds. Let’s look at another one right now!

A New Lens

  1. Set a timer for 5 minutes.
  2. Find the Accessibility Panel and check ‘Enable full-page accessibility tree’
  3. Now click the “Universal Man” button in the Elements Panel.
  4. What is Ignored in the Accessibility Tree that is present in the DOM?
  5. When the timer goes off, share your answer with the other groups by pasting in the workshop thread.

Reflect

Develop Your Skills

  1. Set a timer for 10 minutes.
  2. Discuss how your team will work on developing your skill with Devtools. Make your goals SMART. For example, you might audit a website you have built already with Lighthouse and improve its score using the guides. You might schedule a study group where each person researches and then teaches the group about a different panel in Devtools.
  3. Write down your learning goals with Devtools on a piece of paper and sign it underneath. Elect a new person to represent your group.
  4. Set a timer for 10 minutes.
  5. Popcorn round the representatives and share your commitments.

And that’s it for today! We have covered a lot, but remember, as developers, we are lifelong learners. Always be curious and don’t be afraid to explore new tools and concepts. Soon we’ll dive even deeper into Devtools, so make sure to keep exploring.

More

  1. Inspect web pages as you use the internet. Do this all the time! What font does Youtube use? What about CSS Tricks? Hackernews is still using tables - what’s wrong with this?

  2. Try changing the style and content of some websites. Make your favourite website bright pink. Make the BBC News page tell people about something great you did. Send a screenshot of something cool you changed to your cohort’s Slack channel.

  3. There are crash courses in Devtools all over YouTube and Udemy etc. Find a useful tip and share it in your class channel.

dom-merge-conflict 🔗

DOM Merge Conflicts

This workshop contains a collection of DOM components. For this workshop, you will be creating branches for refactoring and updating the components and then resolving the merge conflicts that arise. You’ll be working in pairs, learning how to handle branching, refactoring, and creating pull requests.

Overview

  • Objective: Learn to resolve merge conflicts that arise during software development
  • Activity: Update and refactor DOM components in two different Git branches
  • Duration: 1 hour

Learning Objectives

  • Describe how merge conflicts can occur in a development setting
  • Interpret a merge conflict message
  • Resolve a merge conflict while preserving changes to the code

Prerequisites

  • JS DOM syntax
  • Access to documentation
  • Some knowledge of how to run tests using Jest

Setup

  • Get into pairs
  • Before starting, ensure you create a fork of this repository on Github to use as a pair. Each person in the pair must clone down the fork of this repository from Github and navigate to the project directory

Instructions

1. Start Branching from main

Each pair will need to branch off from main. Firstly, make sure you both start on the main branch and it’s up to date:

git switch main
git pull origin main

2. Choose a task

As a pair, choose one task from tasks that you will both follow.

3. Follow the task instructions until the end

Choose who will be Person 1 and who will be Person 2 and then follow the instructions in your task’s directory.
Once finished, continue the instructions on this page.

Some tasks will ask you to unskip tests, remove the skip before from the appropriate describe block in this case.

4. Test your changes

Use the provided test suite to ensure your app works correctly. Run the tests according to the task’s testing instructions.

5. Raise a pull request

Once you have tested your changes and are satisfied with the changes, commit your changes and push your branch to the remote repository:

git add <files-you-changed>
git commit -m "<description of change>"
git push origin [your-branch-name]

You should raise a pull request on your pair’s fork of this repository.

6. Handling merge conflicts

Once you have both raised your pull requests, choose one Pull Request to review first and then merge it.

Now you will need to handle the second pull request. For this pull request, you should now have a merge conflict in the remaining pull request.

On the branch to be merged run:

git pull origin main

So that you can resolve the changes locally using Git.

Use this guide from GitHub to resolve the conflict using Git.

When you come to resolve the merge conflict, you need to make sure to keep the updates and refactors. Make sure to test that your app still works.

Once you’ve resolved the conflict, you should be ready to merge the second PR. Discuss with your partner whether the tasks assigned have been completed after both merges.

express-setup 🔗

Express Workshop

This workshop is based on the Node Girls Express Workshop

Fork the express-workshop repository

git clone https://github.com/YOUR-USERNAME/express-workshop
git clone https://github.com/YOUR-USERNAME/express-workshop

Learning Objectives

Requirements

Step 1 - Setting up your project

When creating a Node.js project, you will usually install many different packages along the way. To share your project with others, you need to list those packages, so others can install the same set of packages.

In Node.js, this ’list’ file is called a package.json. The ’things you’ve installed’ are called dependencies. Your dependencies come in little packages, each one labelled and numbered by your Node Package Manager, npm. They are the software your software depends upon to work.

Creating this file is the first step in setting up your project.

1. Make a package.json file

Let’s start by creating the package.json file. We can add things to it as the project grows. The package.json file is easy to create from the command line.

Type the following command into your terminal:

npm init

This command will initialise a step-by-step process for creating the
package.json. You should see something like this:

-> % npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (express-setup)

It will ask you a bunch of questions.

You can skip most of the questions but change the entry point from
(index.js) to server.js.

The wizard asks you for the following information: name, version,
description, main, test, repository, keywords, author, license -
do you understand all of them?

At the end of the wizard, you should see a new file called package.json in your project’s folder.

Here is an example package.json file for a project called
Passport.

What is JSON?

JSON is a type of file for structuring data in a readable way. It is also a really popular format for sending data across the web. JSON is a string representation of a Javascript object. JSON objects convert really easily to Javascript objects, and vice versa, with JSON.parse() and JSON.stringify().

{
  "firstName": "John",
  "lastName": "Smith",
  "isAlive": true,
  "age": 25,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": "10021-3100"
  },
  "phoneNumbers": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    },
    {
      "type": "mobile",
      "number": "123 456-7890"
    }
  ],
  "children": [],
  "spouse": null
}

Step 2 - Installing Express

Today we are going to install Express. Node and Express are not the same thing. Express is not a mandatory step of setting up a Node project or a package.json. It’s just a piece of software we will use a lot.

Before we write any code, you’ll need to install the Express library. We’re going to use the Node Package Manager (npm) to download it using the npm install command.

NPM is the place to go to download other Node code written by other people. There are thousands of open-source, 3rd-party Node modules (also known as “packages”) by other people that you can download and use in your own projects.

As we install Express, we’ll need to update the package.json to add Express as a dependency. We do this so that other people working on the project will know to install Express before running any of the code. Do this by adding
--save to the end of your command.

Run the following command in your terminal:

npm install express --save

Express should now be installed. Check your package.json file to make sure it has been added as a dependency. It will look like this:


          package.json screenshot

Step 3 - Building the server

The first step is to build our server. You will always need to build a server when writing back-end code. A server can be built with in-built Node.js libraries, but Express gives us simpler syntax to work with.

1. Create a server.js file

Let’s build our server! Before we do anything, let’s create a new file called server.js. This is where all our server code is going to live.

2. require the express library

We already installed Express in Step 2, but we need to make sure it is included in this file specifically so we can make use of its methods. In Node.js, when you want to access the functionality of a library or module in another file, you require it. This is like import, which you have already used many times. require is an older syntax; Express is old software.

To import Express, write the following inside server.js:

const express = require("express");

3. Initialise the server

To initialise our server, we need to call the express() function. This will create an Express application for us to work with.

Add the second line of code to your server.js file:

const express = require("express");
const app = express();

4. Start ’listening’ for potential requests

One more step left, we need to set a port for our server to listen to. Think of a port as a door number; any requests that come to the server will come via that door. Setting a port will allow us to find where our server is running.

We use the app.listen method to do this. This method takes two arguments: a port and a callback function telling it what to do once the server is running. Need clarification? Read more about the app.listen method in the Express documentation.

We’re going to run our server on port 3000, and run a console.log as our callback function. Update your server.js file, calling the app.listen method:

const express = require("express");
const app = express();

app.listen(3000, () => {
  console.log("Server is listening on port 3000. Ready to accept requests!");
});

5. Switch the server on!

You’ve built your server, but it isn’t running yet. We need to run a command in the terminal to do this. We are going to use the node keyword to run the server file.

Type the following command in your terminal:

node server.js

If you see this, congratulations! You have built a server!


          success

Step 4 - Communicating with the server

Now that we’ve built the server, we need to communicate with it. We’re going to control the server with handler functions.

What is a handler function?

When a request reaches the server, we need a way of responding to it. In comes the handler function. The handler function is just a function which receives requests and handles them, hence the name.

The handler function always takes a request and response object, and sends the response back to the client along with some information. You can decide what to send back in your response.

What does a handler function look like in Express?

The get() method is used to define a handler function in Express. It takes two parameters: the endpoint at which to trigger an action (we’ll explain more about this in the next step), and the handler function that tells it exactly what to do. Here’s a simple “Hello World!” example:

// req is the Request object, res is the Response object
// (these are just variable names, they can be anything but it's a convention to call them req and res)
app.get("/", (req, res) => {
  res.send("Hello World!");
});

Here, we are telling our server to respond with “Hello World!” when someone
tries to access the webpage.

1. Create your own handler function.

We are now making a handler function with a custom message in our response. You can write any message you want.

Update your server.js file with an empty app.get() function:

const express = require("express");
const app = express();

app.get("/", (req, res) => {});

app.listen(3000, () => {
  console.log("Server is listening on port 3000. Ready to accept requests!");
});

Exercise: Try to console.log the request object inside the handler function. Restart your server, refresh the browser, then go to your terminal to see what it looks like. You should see a lot of data come through.

2. Tell your handler function what to do

We want our handler function to send back a message to the client. To do that, we’re going to use the Express send()
method. This will update the response object with the message.

Update your handler function like so:

const express = require("express");
const app = express();

app.get("/", (req, res) => {
  res.send("Yay Node Girls!");
});

app.listen(3000, () => {
  console.log("Server is listening on port 3000. Ready to accept requests!");
});

3. Check it out in your browser

Quit your server in the terminal with ctrl + c. Then restart it to run your new changes.

node server.js

Now, open Chrome and navigate to http://localhost:3000. If you see your message in the browser, congratulations! You just sent your first response from the server.

Step 5 - Routing

At the moment our server only does one thing. When it receives a request from the / endpoint, it sends back the same response: “Yay Node Girls!”.

Try typing http://localhost:3000/nodegirls and see what happens.

However by making use of endpoints, we can make the server send different responses for different requests. This concept is called routing.

What is an endpoint?

An endpoint is the part of the URL which comes after /. For example:
/chocolate is the “chocolate” endpoint. It’s the URL to which you send a request.

What is a URL?

sequenceDiagram participant U as URL participant P as Protocol participant H as Host participant Po as Port participant R as Resource Path Note over R: (Endpoint) participant Q as Query Params U->>P: http:// U->>H: www.domain.com U->>Po: :1234 U->>R: /path/to/resource U->>Q: ?a=b&x=y

1. Create your own endpoints and send different responses

We’re going to try sending different responses at different endpoints. Remember the app.get() method? To set up routing in your server, we need to repeat this method with different endpoints.

For example:

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.get("/chocolate", (req, res) => {
  res.send("Mm chocolate :O");
});

Exercise: Add some code so that your server sends one message when the endpoint is /node and another one when it’s /girls.

Step 6 - Serving static files

So we know how to send back a simple message. But what if you want to send back a whole HTML page, or an image?

Things like HTML files, images etc are called static assets. If you want your server to “serve” static assets back to the browser, you need to do something different than just using the res.send() method.

To be able to send any file from the server we need a special, built-in
middleware function that comes with Express: express.static(). Read more about it in the Express JS docs.

Say we want to serve all the static assets in our “public” folder. The
express.static() function will look like this:

app.use(express.static("public"));

1. Serve static files from your server

Delete all your app.get endpoint functions, and replace them with the line of code above. Restart your server, refresh your browser and see what happens! If you see a Node Girls CMS, then your static assets have been successfully served.

HTTP request methods

All requests use one of the HTTP methods. The main ones are: GET, POST, PUT, DELETE.

app.get deals with requests that use the GET HTTP method.

We will go into these Methods into more details, but for now:

  • GET is a method for GETting data
  • POST is for POSTing/inserting new data
  • PUT is for updating existing data
  • DELETE is for deleting data

The POST http request method

When sending data to the server, we use the POST http request method, instead
of GET.

Let’s try POSTing some text to the server.

We’re going to add a form to the index.html page, so that you can write your blog posts from there.

Open up the index.html file in your text editor. If you have a look, you should see this:

<div class="entry-container">
  PASTE YOUR CODE HERE!! 
</div>

Replace the greyed-out comment with this code snippet:

<h3>Create a blog post</h3>
<form action="/create-post" method="POST">
  <textarea name="blogpost" rows="10" cols="14"></textarea>
  <button type="submit">Send</button>
</form>
  • This form has a text area and a send button.
  • The action attribute is the endpoint form data will be sent to.
  • The name attribute will be used later to reference the data.

When you hit send, the form will send a POST request to the server. The form will use whatever is in the action attribute as the endpoint (destination). In our case it’s /create-post.

Exercise: Open Chrome Developers tool, click the button and see what happens.

Receiving the blog post on the server

  • Data doesn’t come through the server in one go; it flows to the server in a stream. Think of a stream as water flowing from a tap into a bucket. Your job is to collect this water in the server.

If we were writing a pure Node server, we would have to think about how to collect the stream of data properly. But luckily for us, Express handles all of that stuff.

All you need to do is define a route to deal with requests that come through on the /create-post endpoint.

Let’s remind ourselves of a GET route in Express:

app.get("/hello-world", (req, res) => {
  res.send("Hello there!");
});

Exercise: This time we want to define a route to deal with a POST request not a GET. What do you think you would need to do differently?

Experiment and see if you can define a route for the /create-post endpoint!

For now, make your /create-post handler simply do this: console.log('I am /create-post endpoint').


Extracting the blog post

Now the contents of your blogpost is hidden in your req object somewhere. Normally you would extract it using req.body. Try to console.log req.body now.

Getting undefined? Not to worry, that’s normal. When data has been POSTed to the server as FormData, we need to do things slightly differently to access the data that’s come through in the request.

We need another middleware function. Something that can get extract the contents out of the special FormData object. For this we will use express-formidable. express-formidable is another Express middleware. It will extract the form data from the request and make it available to you when you do req.fields.

This time though, express-formidable is not built-in, we need to install it.

In your terminal, install express-formidable

npm install express-formidable --save

require express-formidable so you can use it in your code. You can’t use dashes in JavaScript variable names, so call it const formidable.

const formidable = require("express-formidable");

Now add this towards the top of your server, after your requires and
app.use(express.static('public')), but before your /create-post endpoint:

app.use(formidable());

Now inside your /create-post function, add:

console.log(req.fields);

Refresh your server and have another go at writing a blog post.

You should now see an object in the console. The key should be blogpost, just like the name attribute in the form on the HTML page. The value of blogpost will be your message!

Exercise: Try putting app.use(formidable()); at the end of the file
(after the create-post but before starting the server)

What is a middleware in Express? Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware. Read more on writing middleware in the Express documentation

Step 8 - Saving your blog post

Right now, your precious blog posts aren’t being saved anywhere, which is a bit of a shame. Let’s do something about that.

You’ll note that in the data folder there’s a new file called posts.json.

If you look at posts.json will see there’s already one blog post there. The format is:

{
    [timestamp]: [blog post message]
}

We’ve used a timestamp as the key so that the blog posts are listed in
chronological order. Also, it’s a record of when the blog post was created.

Writing to your hard drive

Anytime a blog post comes through to the server, we want to save the data on your computer’s hard drive. To do this, we need to use a built-in Node module: fs, which stands for ‘file-system’.

Built-in Node modules - core Node modules - are rather like the built-in Express middleware functions. Only difference is that where you need to have installed Express to use Express middleware functions, the core Node modules come automatically with Node itself.

To use fs, require it at the top of your server file:

const fs = require("fs").promises;

The method we need to write to your hard drive is fs.writeFile.

fs.writeFile("path/to/file", yourData)
  .then(() => {
    console.log("successfully written to the file");
  })
  // do something
});
  • Argument 1: "path/to/file" the location of the file you want to write to
  • Argument 2: yourData the data you want to write

The ‘path/to/file’ will be replaced with the actual path to the file you want to write to. If it doesn’t exist, fs.writeFile cleverly creates one for you. But we already have posts.json, so not to worry.

Reading from your hard drive

To read data that’s already there, you would use fs.readFile. The way to use fs.readFile is very similar to fs.writeFile:

fs.readFile("path/to/file")
  .then(file => {
    console.log(file);
  })
  // do something
});
  • Argument 1: the location of the file you want to read from

Let’s read the data from the posts.json file. Make sure you’ve required the fs core Node module at the top of your server file somewhere.

Add this code to your server (put it anywhere after the requires for now):

fs.readFile(__dirname + "/data/posts.json")
  .then(file => {
    console.log(file);
  })
  console.log(file);
});

(__dirname is a Node global object that gives you a path to your current working directory. It’s handy to avoid writing the whole path out in full.)

If you restart the server, you’ll probably see something like this:

<Buffer 7b 0a 20 20 20 20 22 31 34 36 37 33 39 30 33 35 36 32 39 31 22 3a 20 22 54 68 69 73 20 69 73 20 6d 79 20 76 65 72 79 20 66 69 72 73 74 20 62 6c 6f 67 ... >

This is actually the contents of your posts.json file, but in a format called a buffer. To make it a bit more human-readable,console.log the file to a string, like this:

console.log(file.toString());

file is in JSON format right now. To access the blog post message inside file, we need to parse it from JSON back to a JavaScipt object.

Add this next bit of code to the .then callback for fs.readFile’s:

const parsedFile = JSON.parse(file);

Now parsedFile is a normal JavaScript object, and we can access the data inside it.

Ok, so we’ve talked about JSON and we’ve talked about reading and writing files. You now have the power to save new blog post data to your hard drive! Work with your partner and your mentor to see if you can figure the next steps out on your own.

Here’s a breakdown of what you want to achieve:

  • When new blog post data comes through, read from posts.json to access its contents
  • Add your new blog post data to the old ones.
  • Write your new combined data back to the posts.json file.

Things to remember

  • fs.writeFile() normally overwrites the target file you’ve given it. Chances are you don’t want to lose all your old blog posts every time you get a new one, so think about how you can combine fs.readFile() and fs.writeFile() to prevent overwriting.

  • You will need to convert between JSON and a JavaScript object several times. JSON.parse() and JSON.stringify() are what you need.

Oh by the way, if you want to get the current timestamp, use the JavaScript Date.now() method.

Step 9 - Displaying your blog posts

So now we’re saving the blog posts to the server, it’s time to display them in the browser!

Look inside public/script.js. There’s a whole bunch of JavaScript code in there. Don’t worry about what all the code means, just know that it’s responsible for sending a request to GET old blog posts and display them on the page underneath “Recent Posts”.

script.js is trying to load existing posts by making a GET request. Look inside script.js and see if you can find any useful endpoints.

Your script.js file will want to receive the JSON containing your blog posts. Your job is to make that happen!

Express has a handy method called res.sendFile() that makes it easy to send files back to the client. Feel free to use this with your JSON.

If all goes well, you should have a fully functional CMS!

Stretch

For a really good workout, redo this workshop using

  1. Node and Next.js
  2. Deno and Oak

Acceptance Criteria

  • I have created an Express server

get-forms 🔗

Get Forms

This workshop is about writing forms in HTML.

Note: this workshop is deployed to Netlify at https://cyf-workshop.netlify.app/get-forms and branch previews are turned on. Any PRs opened to main will be deployed automatically and can be looked at via the bot link on that PR.

Learning Objectives

Requirements

Before you start, make sure you’ve done your prep work on forms and worked through some of the examples in the HTML forms section of MDN.

Today we’re going to build a form that interacts with GitHub Search. It’s a bit unusual for a form as we are writing a GET method, where the form requests, or gets data, instead of a POST method, which sends data.

Next, we’re going to swap our forms with another group and test the form we made.

Last, we’re going to make changes based on the test feedback. Because it’s important that software works and that people can use it.

But first, everybody needs to be ready to participate.

🧰 1. Setup

Getting Set Up

  1. Set a timer for 10 minutes.
  2. Fork this repository to your own GitHub account.
  3. Clone the repository to your machine.
  4. Checkout a new branch called cohort/your-name.
  5. Open get-forms/index.html in VS Code.

📖 GitHub Search Project Briefing:

Create a form so the user can search GitHub repositories based on specific criteria.

👤 User Stories:

  • As a user, I want to search on GitHub.
  • As a user, I want to sort my results by stars, forks, or when last updated.
  • As a user, I want to sort my search results in my preferred order, ascending or descending.

✅ Acceptance Criteria:

US1: Search Field

Given I am on the GitHub search form,
When I select the search field,
Then I should be able to type in my search query.

US2: Sorting Results

Given I am on the GitHub search form,
When I choose from options of stars, forks, and updated.
Then the results are sorted by stars, forks, or last updated.

US3: Options for Sort Order

Given I am on the GitHub search form,
When I choose a sort order
Then the results should be sorted in my preferred order, ascending or descending.

Overall Acceptance Criteria

Given I am on the GitHub search form,
When I run Lighthouse
Then the Accessibility score is 100.

2. 🧱 Build the form

Get results from GitHub

  1. Set a timer for 45 minutes.
  2. Work in pairs.
  3. Read the project briefing carefully.
  4. Look in the resources section for help with the elements you might need.
  5. Write your HTML in get-forms/index.html. Do as much as you can, leaving time to open your PR (10 or 15 minutes).
  6. Open a pull request to this repo with your work. Your PR will show up in the list of PRs for this repo and a deploy preview will be created and linked on your PR. Explore this.

3. 🧪 Test the form

Test the form

  1. Set a timer for 15 minutes.
  2. Swap your form with another group by choosing the PR directly above yours in the PR list. If you are at the top of the list, choose the PR at the bottom of your group!
  3. Test your colleague’s form against the acceptance criteria.
  4. Comment on their pull request with what you have found.

4. 🫠 Review and respond

Review the test results

  1. Set a timer for 15 minutes.
  2. Read the comments on your pull request.
  3. Make changes you need to make to your form to pass the acceptance criteria.
  4. Commit and push your changes to your branch; your pull request will update automatically.
  5. If your pair doesn’t have changes, join a team that does and help them.

Resources

git-cli 🔗

💡 Purpose

Currently, you’re using the 🎮 VSCode interface to interact with Git.
However, we can often use different interfaces to carry out the same tasks.

In this workshop, you will use the Git CLI - Command Line Interface to interact with Git.
In addition, you will:

  • Consolidate existing knowledge of Git
  • Develop your mental model of the working tree and the staging area
  • Learn to use basic Git CLI commands

📝 Learning objectives

During this session, with the Git CLI, you will:

🧰 Setup

Work in pairs:

  • Assign one person to be driver (the driver will control the keyboard and do the typing)
  • Assign another person to be navigator (the navigator will read out the questions and explain how to tackle the problems).

The driver must ensure they have a clone of this repo on their local machine.

📜 Instructions

Follow the link to the readmes for further instructions:

Head to the Starting point for more instructions

git-day-1 🔗

Part 1

Setup

  • Break out into groups of 5/6 ( depending on volunteer and trainee numbers )
  • Use these instructions as a guide to check your understanding, resolve misconceptions and develop your understanding

This workshop starts with a recap based on this week’s prep material…

Exploring GitHub repositories

Recap activity 🕹️

  • Trainees do this section in pairs
  • ⏲️ 10 mins

Let’s recap some of the things from earlier in the week.

Visit the following repository on GitHub: https://github.com/CodeYourFuture/cyf-demo-repo

Answer the following questions:

a) How many commits are there in the cyf-demo-repo project?

b) Who committed on Oct 31, 2020?

c) What changes did illictonion make in the commit titled “Revert changes accidentally pushed in the past”?

d) How many files were added in the first commit? What were the names of the files?

e) What is the hash for the first commit in the history?

f) What is Claire Bickley’s favourite food?

🧵🗣️ group discussion

  • Group discussion
  • ⏲️ 10 mins
  • A volunteer will need to facilitate this section

A volunteer can facilitate this group discussion by going through the questions above and asking pairs for their feedback. If pairs are unsure / not quite accurate then spend a small amount of time addressing misconceptions.
Remember to ask around for feedback.

Creating a fork 🍴

🕹️ Recap activity

  • Trainees do this section in pairs
  • ⏲️ 5 mins

Use the guidelines from the prep section of this week to create a fork.

  1. On one person’s computer, fork this repo: https://github.com/CodeYourFuture/cyf-demo-repo
  2. 📝 Double-check the URL of your forked repo. How can you tell the fork was successfully created?

Group discussion/demo 🧵 🗣️

  • Groups discussion
  • ⏲️ 5 mins
  • A volunteer will need to facilitate this section

A volunteer will need to navigate and let the group guide them in creating a fork as per the steps in the previous section.

🌀 Cloning a repository

🕹️ Recap activity

  • Trainees do this section in pairs
  • ⏲️ 5 mins

📋 Check your understanding

Before continuing, try answering the following:

❓ what is the difference between a fork and a clone.

Remember to check your answer before continuing.

  1. Clone your fork of cyf-demo-repo to your local machine.
  2. Open this local repository using VSCode.
  3. Use pwd in your terminal to check you’re in the right place.

Group discussion/demo 🧵 🗣️

  • Group discussion/demo
  • ⏲️ 5 mins
  • A volunteer will need to facilitate this section

A volunteer will need to navigate and let the group guide them in following through the steps in the previous recap activity.

🌳 Creating a branch

🕹️ Recap activity

  • Trainees do this section in pairs
  • ⏲️ 10 mins

Next, create a local branch called week-1-workshop

Group discussion/demo 🧵 🗣️

  • Group discussion/demo
  • ⏲️ 10 mins
  • A volunteer will need to facilitate this section

Take a break for 10 mins… 🍫

Part 2 - New skills 🧰 - Committing and pushing 📸

Learning objectives

🕹️ Activity - Figure it out 🔍

🎯 Goal: Make some local changes and create a local commit on our branch.

  • Do this section in pairs
  • ⏲️ 15 mins

Follow these instructions carefully.

Our Git timeline starts off with some commits like this:


          main-and-feature-in-sync

We’re going to figure out how to

  • make local changes and commit them to our branch “week-1-workshop”,

so our history looks something like this:


          feature-branch-ahead

where the most recent commits contain our changes.

To create a commit, we can use the following steps (explained more below):

  1. Make a change to a file
  2. View the local changes
  3. Stage the changes
  4. Creating the commit

🗄️ 1. Make a change to a file

  1. Open up your local repo cyf-demo-repo in VSCode.
  2. Go to the Explorer section of VSCode ( look for a 🔍 icon ).
  3. Find file.txt and edit the file with the answer to the questions.
  4. Remember to save the changes to file.txt.

Tip:

  • You can use Cmd + S on a Mac to save changes to a file in VSCode.
  • You can use Ctrl + S on a Linux OS to save changes to a file in VSCode.

🔬 2. View the local changes

We want to view the changes we’ve just made to our working directory.

  1. Locate the Source Control tab in VSCode.
    
          source-control-tab
  2. Go to the Changes section and click on the file you changed - this should now show the changes for the file.
  3. Try editing the file again in the Explorer tab and check to see the update is visible in the Source Control panel

🟢 3. Stage the changes

We need to tell Git which changes we want to be part of our next commit.

Each commit is a checkpoint we’ve decided to save. When making a commit, we can decide to not include all of our changes in the checkpoint, but just include some of them.

We choose which changes we want to include in a commit by staging our changes.

In the Source Control tab again…

  1. Go to the file file.txt and click on the +.

👓 Notice what happens when you carry out step 1.

  1. View the Staged Changes area in your Source Control panel.

📸 4. Create the commit

Once we’ve staged our changes, then we can commit these changes.

Before we do, we should make sure we’re on the correct branch. Check that you’re on the week-1-workshop branch.

Your VSCode window should look like this:


          check-current-branch-week-1-workshop

and not like this:


          check-current-branch-is-main

If you’re sure you’re on the right branch:

  1. Enter a commit message describing briefly what you did in your commit.
  2. Click Commit to create the Git commit.

📝 Now figure out how many commits you have on your local machine.

🧠 Explain what you think would have happened if you didn’t stage anything in your working directory when you made your commit.

When you’re finished…

❗ Once you’ve completed this commit, swap roles in your pair.
Choose another file and then go through the steps in the Creating a commit section

Group discussion/demo 🧵 🗣️

  • Group discussion/demo
  • ⏲️ 10 mins
  • A volunteer will need to facilitate this section

A volunteer will now need to navigate with directions from the group. Go through the git commit steps together.
Also use this time for clarifying questions.

🫸 Pushing

🎯 Goal: Push a branch to a remote repository

🕹️ Activity - Figure it out 🔍

  • Trainees work in pairs
  • ⏲️ 5 mins

After committing your work on your machine, you’ll have a local branch that looks like this

--- title: cyf-demo-repo --- gitGraph commit commit branch "week-1-workshop" commit commit

📋 Double-check you’ve been committing to your branch week-1-workshop branch and not your main branch.

However, our remote fork only has a main branch:

--- title: cyf-demo-repo --- gitGraph commit commit

In other words, we have not added our local branch onto the remote fork on GitHub.

To do this, we must push our branch onto GitHub.

push means adding local work to a remote GitHub repository.

🔍 Figure out how to push your local branch to the GitHub repository using the Source Control interface in VSCode.
🔍 Figure out how to check the week-1-workshop branch is on the remote fork.

Group discussion

  • Group discussion/demo
  • ⏲️ 5 mins
  • A volunteer will need to facilitate this section

A volunteer will need to navigate and let the group guide them in following through the steps in the previous recap activity.

🧵 Tying things up

Now is some time to wrap up and try and discuss some of the key concepts from this week.

🗣️ Discussion in pairs

  • Trainees discuss in pairs
  • ⏲️ 10 mins

In your pair, discuss the following questions/tasks:

  1. what is a commit? explain why need to make commits when we’re developing a project?
  2. explain why we store repositories on GitHub
  3. describe the purpose of VSCode
  4. explain the difference between Git and GitHub
  5. explain why developers use branches
  6. explain the difference between a fork and a clone?
  7. what does the branch name origin/main mean instead of just main
  8. Check out the following git repository diagram below:

How many commits are in common between week-1-feature and main?

--- title: cyf-demo-repo --- gitGraph commit commit commit branch "week-1-feature" commit commit

🗣️ Group discussion

  • Discuss the questions together as a group. Go round and get feedback from each person in the group.

goblin-breakdown 🔗

Goblin Breakdown

Use AI to break down coding problems into smaller pieces.

Prompt

If Goblin is offline, use any LLM with the pre-prompt “Break down this task into single responsibility functions”.

Learning Objectives

Requirements

We’re practising breaking down our problems again. It must be Saturday!

This time we’re going to use AI to help us. Goblin is a small, clever integration with ChatGPT that makes magic todo lists. We’re going to use it to break down our problem and plan our solution.

🧰 1. Setup

You should already be set up but just in case, you need to open the Goblin workshop in VS Code. Set a whole class timer for 5 minutes.

Getting Set Up

  1. Fork the CYF-Workshops repo to your own GitHub account if you have not already.
  2. Clone the repository to your machine.
  3. Open in VS Code and go to the goblin-breakdown folder.
  4. Look at the contact folder. It contains a file called index.js. This is where you will write your code. Look at data.json to see an example of the data returned from the API.

👣 2. Break down coding problems

Let’s try breaking down a coding problem. Let’s do a sample problem together. Set a whole class timer for 10 minutes.

Planning a Solution 10m

Format a UK address and UK phone number from a JSON object and show it as HTML on the page

  1. Paste the above problem into Goblin and press the 🪄 wand button.
  2. Goblin will give you some steps. In the contact folder, paste each of the steps into index.js as comments. There are some samples given but your Goblin might be a bit different. Feel free to delete the existing examples.
  3. You likely have around five steps. Under each comment, write the name of the function you will write to achieve the step. Two are given as an example. Don’t write the function out, just the name and leave the function empty.
  4. Now you have planned your code! If you have time, start writing the functions.

Sample Solution

There isn’t a “right answer” to this workshop. If you want to see a basic solution, look in the contact folder for the file completed.js.

🧠 3. How can you use this?

Set a whole class timer for 10 minutes.

Reflect and Discuss 10m

Reflect on this process of breaking down the problem and planning your solution. Discuss with your pair or group.

  • How can you use this process in your own work?
  • What are the benefits of breaking down a problem?
  • What are the risks of having an AI break down a problem? How can you mitigate those risks?
  • What are the benefits of planning your solution?
  • Why does CYF want to make you write such small functions?
  • How could doing these steps make writing your code easier?

Acceptance Criteria

  • I have used AI to produce a step-by-step plan for my solution
  • I have written comments to structure my code
  • I have produced a planned solution to a coding problem
  • I have reflected on this process and discussed it with my pair or group

js1-wk1-eval 🔗

JS1 week 1 evaluation

🎓 Instructions

This workshop aims to check your understanding.

Each task will explain whether or not you should run the code.

  • For each task, you can use JS1 week 1 prep to help you with the questions.
  • You can also use documentation to look up any functions that are unfamiliar.
  • Don’t use ChatGPT or any other AI tool to help you.

🧰 Setup

👉 This workshop lives on CYF-Workshops on GitHub

  1. Get into pairs or groups of up to three.
  2. Make sure you have a clone of the CYF-Workshops repository on your local machine

Each file contains a different problem at a particular level. Start this project at Level 100 and then move up through the levels: level 200, 300

🏁 Go to Level 100

node-challenge-london-mini-guide 🔗

Node Challenge - London Mini-Guide

In this challenge you are going to build a full stack application (server & client) that shows the number of hospitals, doctors, pharmacies and colleges in some of London’s boroughs.

This exercise is designed to develop your pair programming skills and to get you thinking about how to design a full stack application. You’re not expected to get everything completed.

Server

The Server Challenge

Client

The Client Challenge

Time to Complete

This challenge has three levels. Budget one hour to complete the first level. If you have more time, do more levels.

Instructions

Split into groups of two or three people.

One person will start as the driver (typing the code) and the others will begin as the navigators.

You must complete the first level before moving on to the second level. Do not jump around.

Begin with the server challenge.

Live Version:

https://london-mini-guide-challenge.netlify.app/


          project screenshot

Data Source

The data is provided to you in a folder ./data which contains 3 files: Harrow.json, Heathrow.json and Stratford.json.

Each file in this format:

{
    "pharmacies" : [
        {
            "name" :
            "address":
            "website":
            "phone" :
        }
    ],

    "colleges" : [
        {
            "name" :
            "address":
            "website":
            "phone" :
        }
    ],

    "doctors" : [
        {
            "name" :
            "address":
            "website":
            "phone" :
        }
    ],

    "hospitals" : [
        {
            "name" :
            "address":
            "website":
            "phone" :
        }
    ]
}

Data source: https://www.yell.com/

Data has been collected using a technique called web scraping.

Optionally, to know more about web scraping, check out these resources:

objects 🔗

Instructions

This workshop aims to check your understanding.

Each task will explain whether or not you should run the code.

For each task, you can use JS2 week 2 prep
to help you with the questions.
You can also use documentation to look up any functions that are unfamiliar.
Don’t use ChatGPT or any other AI tool to help you.

🧰 Setup

  1. Get into pairs or groups of up to three.
  2. Make sure you have a clone of the CYF-Workshops repository on your local machine

This workshop can be found here 👉 https://github.com/CodeYourFuture/CYF-Workshops/tree/main/objects
In this workshop, each file contains a different problem at a particular level.

You should start this project at Level 100 and then move through the levels in ascending order, level 200, 300 etc.

➡️ Go to Level 100

playing-computer 🔗

🎮 Playing computer

💡 Purpose

This workshop is designed to develop your understanding of playing computer. Playing computer means simulating how the computer executes our code. We “step through” the code, line by line, and work out what the computer does when it follows each instruction. Once we develop a better intuition for how our code runs it becomes easier to debug code, reason about it and write more complex programs.

📝 Learning objectives

During this session, you will:

Resources

You will need:

  • A piece of paper saying “memory” - where we store variables
  • A piece of paper saying “console” - where we print to the console
  • Some example programs like the ones here 👉 Playing computer workshop
  • [Optional] A set of functions in envelopes ( this isn’t essential but a nice thing to have to reinforce the idea of instructions being “opened” up when a function is called )

( If you don’t have any paper/pens you can create plain text files for “memory” and “console” and write your work out in there! )

🧰 Setup

  1. Split up into groups of 2 or 3 at most.
  2. Start with the first example ( e.g. example-0.js )
  3. Each person will need to take responsibility for a particular frame. One person will be assigned the role of global frame, for example. If there are other function declarations, someone else will “play” that frame too.

🍲 Warm-up

Start with the program in example-0.js. There is only one frame to play here - the global frame, as there are no other function declarations and calls in the file.

  • One person will “play” the Global frame
  • This person will step through the code in example-0.js using the rules of execution below.
  • Other members of the group can watch and provide support as they go through the code.
  • Once you’ve finished you can change some of the values/variables and then someone else can play the global frame too
  • ❗ After you’ve finished playing computer with the program, you should check your memory sheet and console sheet by using the Python visualiser

Rules of execution

Rule 0

Only one person can be sat at the table at a time ( where we write to the memory sheet/console sheet)

Rule 1

Start reading code from top to bottom, one line at a time

Rule 2

Write and update variables in memory as you go along
For example, if the program says:

let a = 32;

You would write down “a : 32” on your piece of paper saying “memory”

Rule 3

If a function is called the person “playing” this frame takes the seat and we jump to the instructions in that function, using Rules 1 and 2.

Rule 4

When a function returns or finishes execution this person leaves their seat and the previous person sits down again.

You may need to play computer like this a few times before you get used to this way of thinking about the code. Make sure you swap roles so others get the chance to play a particular frame.

📝 Check your understanding

Doing this activity by hand is a great way to start thinking about how your code runs.
Once you’ve gone through this activity and played computer with pen and paper, you can check what you’ve got on your piece of paper by playing computer with the Python Tutor code visualiser

polish 🔗

UI Polish

In this workshop we will take our existing projects and polish them to a higher standard. We will use Lighthouse to evaluate our work and make improvements. We will apply some basic design principles to bring a professional look to our work. (We can talk about polishing code in another workshop.)

You can do any or all of the steps in this workshop before you arrive, as well.

Learning Objectives

Requirements

This workshop is all about small changes that make a big difference. We will not be adding many large new features. We will be making small changes to the front end to make it look and feel more professional. By the end of this workshop, your project should look like a professional website, and you should have internalised some habits of highly effective developers.

We will make these changes in a structured way. We will use Lighthouse to evaluate our work and identify areas for improvement. We will identify a few simple changes to make to our front end. We will then implement these changes and re-evaluate our work.

🍅 We’ll do this in five pomodoros and you will need about three hours in total. Please take breaks!

Prep

Before you begin your changes, make a new branch and name it polish-workshop. Do all your work in here, so you can easily swap back and forth to see your improvements. Make sure to commit and push to your branch as you work, because at the end you will need to share your changes with a colleague.

1. 🧪 Lighthouse, 4 green lights

✅ Checklist

  • Accessibility score is 100
  • Performance score is over 90
  • SEO score is 100
  • Best Practices score is 100

Start with Lighthouse. It’s your best friend when building a quality UI. Of course it is possible to build a good front end that doesn’t score well on Lighthouse, and a bad front end that scores perfectly, but use your brain, please.

Audit your design 🍅

Run Lighthouse and revise until you get four green lights

  1. Inspect your page and go to the Lighthouse tab
  2. Check only the Accessibility tab, and hit Analyze Page Load
  3. Fix any accessibility issues, follow the links in the report to help you
  4. Once you have a 100 Accessibility score, check only the Performance tab, and hit Analyze Page Load, and so on, until the timer runs out

⚠️ Note: Size your images correctly

Lighthouse should now pick up images with popped aspect ratios. If you have any images that are not sized correctly, fix them. Compress your images and deliver appropriate sizes to appropriate devices. Janky looking pictures make you look amateurish. Lazy load any images below the fold. You can do this with an attribute or a library.

🎨 2. Fonts, colours, and spacing

✅ Checklist

It may be helpful to know the user agent type scale is roughly 10px, 12px, 16px, 18px, 24px, 32px.

Get out of your own way a bit here. If you are only looking for Cloud roles or something without any visual interface development, then use Tailwind, which has all this pre-set for you and will look basically fine.

What you must do is make your UI look intentional. It’s fine to be experimental, it’s fine to be basic, it’s fine to use a design system, but it’s not fine to have a UI that looks like you’re not in control of it.

Rationalise your design 🍅

Rationalise

  1. Pick a colour palette (5m)
  2. Define your palette as variables in your CSS (5m)
  3. Work through your entire UI and replace all colour values with variables (10m)
  4. Link your colour palette in your README (5m)

If you already have a colour palette, do your type or spacing.

📐 3. Gutters

Hey, have you centered everything? 😱 Does your layout look like a messy triangle? 💩 Are elements touching the edges of the viewport by mistake? If you run your finger down the left edge of your components, are they lined up or is it all a jagged game of Jenga? 🍻🥴 Do you have any kind of grid in your design or is it all just sort of individual components floating around, plonked on the page? 🫠

  • Gutters are consistent, drawn from a limited, designed scale
  • Components are laid on a grid, with consistent gutters

Line up your components 🍅

Line up your components

  1. Take a piece of paper and sketch your page layout as it is now
  2. Take a new piece of paper and sketch your page layout as you want it to be
  3. Draw a grid over your sketch
  4. Write that grid in your CSS and align your major components to it
  5. If you already have an aligned grid, polish your type, spacing, or readme.

4. Spellcheck S.P.A.G

  • There are no spelling errors in the interface or README
  • Long form text is grammatically correct and I have checked this with Grammarly
  • LOREM IPSUM is not bunged all over the place

Do this last, always, as you will only add more typos in if you do not. We are all only human beans.

There’s nothing worse than claiming to have great attention to detail and then linking a website called My Protfolio.

Typo Tomato 🍅

  1. Install Grammarly Desktop and run it on your front end
  2. Install a spellchecker in your VSCode
  3. Run these tools and fix any errors you find.

5. Get a review, give a review

You’ve been working largely solo today, but now you will need a partner. Split into pairs and swap your sites. The great thing about reviewing someone else’s work is that it gives you some insight into how your own work may be viewed from the outside.

Review 🍅

  1. Open a pull request from your branch to your trunk (main)
  2. In your PR, write what you’ve done so far and what you plan to work on later. Ask for some specific advice on something you’re not sure about.
  3. Now go to your partner’s PR.
  4. Read the PR message to understand the changes your partner has made.
  5. Read the README to understand the goal of the app.
  6. Run Lighthouse and note any errors on the code review interface
  7. Use Grammarly to examine the spelling and grammar, is it all correct? Note any errors on the code review interface.
  8. Make any more comments and respond to the PR message.

Acceptance Criteria

  • My interface looks like I meant to do it
  • I have run Lighthouse and I have 4 greens
  • My README actually explains my product
  • Someone else has reviewed my interface and agrees with my evaluation

Stretch

5. PWA

  • PWA is green

If you have already polished your front end to a high standard, use this time to develop a service worker.

You can either hand-write a service worker or use something like workbox. Most people use workbox. You don’t need to do anything fancy here, just provide an offline page and a manifest.json file. You can learn more about PWAs on web.dev: Learn PWA.

If you need to make a set of icons, which you probably do for your serviceworker manifest, explore the many online services that create these sets. There are also CLI programmes to do this. It’s a whole tiny world. I like the realfavicongenerator.

questions-and-reviews 🔗

Question and review workshop

Getting setup 💻

Please follow the steps below:

  1. The whole group should split up into separate breakout rooms. Then each breakout room / table should split up into pairs.

  2. In your pairs, label yourselves person 1 and person 2 - it doesn’t matter who is 1 or 2, you’ll end up swapping. 😄

  3. You will end up swapping roles frequently during this activity.
    To begin with, Person 1 fork this repository and clone it to your local machine.

  4. Person 2 should clone Person 1’s fork to their local machine.

  5. Once it is cloned, in Github desktop, Person 1 should go to Branch at the top of the window and click New branch… and then enter a name: js-2-week-1-questions. Don’t worry if you don’t understand what branches are - they’ll explained in depth later on in the course.

Answering questions ❓

In this next section, you’ll need to answer some questions ❓

N.B: You may struggle to answer some or all of the questions in this section: however, we’re not trying to trick you or catch you out! It’s important you try answering in your own terms in this section! You’ll really feel the benefit from trying to answer questions that may appear tricky at first.

So for the first question, Person 1 and Person 2 can read the first question.

  • Person 2 try and answer the question out loud in your own words.
  • Person 1 should write down Person 1’s answer in the file and then commit and push your changes.

Then swap over ( so Person 1 now becomes Person 2 and vice versa ) and try the next question.

❗🕥 Don’t spend longer than 3 minutes on each question

You’ll find the first question in js-1-week-2/0.md

Whole group discussion

After you’ve answered questions. The whole group should go through the questions and a volunteer can invite responses from the different pairs. This is a good opportunity to correct, clarify and consolidate our answers collectively.

Review time

After the group discussion, every pair should raise a PR from Person 1’s forked repo to the origin repo. Then ask for feedback by requesting a review of the PR from the pair that is sat to the right of you. Each pair should then review the PR they’ve been requested to review.

react-pokedex 🔗

Pokedex

This is a staged workshop which can be run over multiple weeks. Trainees will work on their own Pokedex app that displays information about Pokemon. The workshops will focus on different aspects of React, embedding concepts covered in the prep work.

Requirements

You need to complete the prep work for this sprint before starting this workshop. If you haven’t done the prep, you’ve made an error in judgement. You will not be able to participate in this workshop effectively.

The prep is on https://curriculum.codeyourfuture.io/react.

There is a sample blank React app in the pokedex folder for mentors to work with. Trainees should work on their own Pokedex app in their own Module coursework repo. (Probably something like Username/Module-React.)

Workshop 1 : Components, props, and state

/pokedex-1/readme.md

Workshop 2 : Events and interaction

/pokedex-2/readme.md

Workshop 3 : Effects and forms

/pokedex-3/readme.md

Workshop 4 : Routing

/pokedex-4/readme.md

reporting-bugs 🔗

Asking Questions 101

Prep

  • Read this article about Mental Models
  • Review the Asking Questions workshop and the CYF Guide to Asking Questions on the curriculum.

Today we’re going to build on our formal language of developer questions. We began with this basic format:

  1. What I did
  2. What I expected
  3. What actually happened

This format helps to find the discrepancies between expectations and reality. (This is the gap in our understanding.)

It’s also an efficient way to share our current understanding with others. Now we’re going to use this to write a really good bug report. A well-written bug report can help developers identify, reproduce, and fix issues more efficiently. We will follow this basic format:

  1. Steps to Reproduce (What I did)
  2. Expected Behavior (What I expected)
  3. Actual Behavior (What actually happened)
  4. Environment Details 🆕

Clarity is our goal

Exchanging incomplete information sets 30m

ContextOver and over, especially during The Launch, we see trainees writing panicked, incoherent questions with no context, pasting error messages they clearly have not read, and not even sharing the link to the code they're working on.

Outside our community, developers will ignore or delete your posts if you do this. At home with us, well-meaning mentors often try to help you, but they can’t because you haven’t given them the information they need. It feels so frustrating, and people can get really upset. We want to help you avoid this as you prepare to work in a professional environment. Your colleagues will enjoy answering your questions if you give them the information they need; most developers really like solving well-constructed puzzles.

😎 Useful questions -> colleagues enjoy answering -> get solutions promptly -> make lots of progress -> good performance
😰 Not useful questions -> colleagues avoid answering -> don’t get solutions -> take much longer -> performance appears poor

Steps to Reproduce

When you’re writing a bug report, you need to be able to reproduce the bug. This means you need to be able to make it happen again. The person reading the report needs to be able to follow your steps and cause the same error.

Here’s an example of steps to reproduce:

  1. Go to my deployed site at https://my-site.com
  2. Click the “Login” button top right
  3. Choose “Sign in with GitHub”
  4. Authorise with GitHub and be redirected back to the site
  5. Login page error says To confirm your identity, sign in with the same account you used originally.

Bad bug reports

Inversion, 5m

  1. Set a timer for 5 minutes.
  2. Popcorn around the room and each person give an example of a bad way to ask a question until the timer goes off. For example:

“I was on the site, and then I clicked something, and it didn’t work!”

Why are these not useful?

Inversion 2, 10m

  1. Set a timer for 10 minutes.
  2. Popcorn around the room and each person give a reason the previous question was bad until the timer goes off. For example:

“What site are you on? What are you trying to do? How can I read your post and re-create the circumstances. Be specific! Share what you see.”

Expected behavior

What you expected to happen

When you’re writing a bug report, you need to be able to explain what you expected to happen after you executed the steps you just described. You might feel this is so obvious that you don’t need to write it down, but this assumption is drastically, drastically wrong.

Here’s an example of expected behavior:

“I expected to be able to log in with my GitHub account and be redirected to the logged-in view of my dashboard on my site.”

Actual behavior

What actually happened

Here’s an example of actual behavior:

“Instead, I was redirected back to the login page with an error message that says To confirm your identity, sign in with the same account you used originally.

Spot the difference, 5m

Look at the difference between the two examples above. What do you notice? Apart from the user’s reported problem, what is the difference between the actual behaviour and the expected behaviour? It’s subtle.

  1. Set a timer for 3 minutes.
  2. Popcorn around the room until you spot the difference.

Error messages

What the computer told you

Have you ever considered, and this is just a wild idea, reading the error messages that your computer gives when it goes wrong?

Just kidding! We know all trainees are implacably opposed to reading error messages. But here’s the thing:

  1. When you’re writing a bug report, you need to include the error messages you’re seeing. This is crucial information for anyone trying to help you.
  2. You also need to read the message yourself first. If you cannot understand it, you need to say what you don’t understand about it. This is the gap in your understanding that you need help with.
Here's a common exchange we see:

Trainee

I am unable to run my code. Every time it’s saying this; npm ERR!

Missing script: "dev"
npm ERR!
npm ERR! To see a list of scripts, run:
npm ERR!   npm run
npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/student/.npm/_logs/2024-02-26T19_28_05_701Z-debug-0.log

Mentor

What happened when you followed the suggestion in the error message?

Trainee

…What suggestion?

Spot the instruction, 3m

  1. Set a timer for 3 minutes.
  2. Popcorn around the room and find the instruction in the error message.
>

Error messages aren’t always correct, but they are a valuable clue.

  1. Read the error message
  2. Identify suggestions
  3. Find out what they would do (this also means being able to form a hypothesis to test)
  4. Then (maybe) do them.

Environment Details

The conditions in which the bug occurred

When you’re writing a bug report, you need to be able to describe the system you were using when you encountered the bug. Because all these details matter!

Here’s an example of environment details:

VSCode on Windows 10, Node v14.15.4, NPM v6.14.10, React v17.0.1, deployed to Netlify.

Let’s improve a bug report together to understand why details like this matter.

Iterative improvement of a bug report 15m

🐛 Bug Report Fail

Bug: I can’t create any files in my project
I’m trying to create files in my repo but it just errors. I don’t know what’s wrong. Please help me!

This is a terrible bug report. Popcorn around the room and name four problems with it.

🐛 Bug Report Improvement 1

Bug: cannot create new files on the command line

Steps to reproduce:

  1. Open repo in VSCode
  2. Try creating a new file in the terminal
  3. Get error that says I can’t create the file.

Expected behaviour

I expected to create a new file in the terminal

Actual behaviour

Instead, I got an error message

OK now we have some more information given. We’ve got some steps to reproduce and some expected and actual behaviour. But it’s still not great.

Step by step improvement, 5m

  1. Set a timer for 5 minutes.
  2. Popcorn around the room and name three problems with this bug report. How should it be improved?

Send it back!

🐛 Bug Report Improvement 2

Bug: cannot create a new file on the command line

Steps to reproduce:

  1. Open repo in VSCode
  2. Open terminal and type touch newfile.js
  3. Get error 'touch' is not recognized as an internal or external command, operable program or batch file.

Expected behaviour

  • I expected to create a new file in the terminal using the touch command.

Actual behaviour

  • Instead, I got an error message 'touch' is not recognized as an internal or external command, operable program or batch file.

Precision and clarity, 5m

Our bug reporter has worked hard on improving their bug report. But there is one crucial detail missing.

  1. Set a timer for 5 minutes.
  2. Popcorn around the room and guess/suggest how this bug report could be improved with one more detail.

🐛 Bug Report Final Form

See how much easier is to fix in the final form? What is the bug in this report?

Bug: cannot create a new js file on the command line

Steps to reproduce:

  1. Open repo in VSCode
  2. Open terminal and type touch newfile.js
  3. Get error 'touch' is not recognized as an internal or external command, operable program or batch file.

Expected behaviour

  • I expected to create a new file in the terminal using the touch command.

Actual behaviour

  • Instead, I got an error message 'touch' is not recognized as an internal or external command, operable program or batch file.

Environment details:

VSCode on Windows 10, Node v14.15.4, NPM v6.14.10, React v17.0.1, deployed to Netlify.

Wrapping up

Recapping the key points:

Include as much context as you can, including links, line numbers, sample code, etc. Use code blocks to mark up your code. If you use screenshots, they should only show the visual render (never screenshot code - paste code as text).

🧑🏾‍💻🙋 Bug reports contain

  1. 🔗 Links 👍
  2. 🎯 Objectives - what are you actually trying to do? 👍
  3. 🖼️ Screenshots of UI if relevant 👍
  4. 📝 Code blocks 👍
    • In Slack, proper code snippets get syntax highlighting and can be collapsed vertically - remember to 🧵 use threads too
  5. 🪸 Environment details 👍
  6. 📷 Screenshots of code 🙅

📚 Further reading


          Bug fixing friends

sql-quiz 🔗

SQL Showdown: Team Quiz

Welcome, SQL warriors! Today, we’ll be putting your database knowledge to the test in a team quiz. Prepare to unleash your SQL prowess and collaborate with your squad to conquer the challenges.

Learning Objectives

  • Work through various SQL queries, testing your knowledge on selecting, filtering, manipulating, and aggregating data.
  • Collaborate with your teammates, discussing approaches and problem-solving together.
  • React quickly and apply your SQL knowledge under a time limit, simulating real-world scenarios.

Requirements

  • Quiz Leader: The quizmaster needs to prepare the questions, guide the quiz, and keep the energy high. Sample questions are provided below, but you should set your own. Anyone: trainee or volunteer can take this role. Prepare your quiz questions and answers in advance.
  • Timekeeper: Keep track of time for each round to ensure the quiz runs smoothly.
  • Assemble Your Team: Get into groups of 3-4. Teamwork makes the dream work
  • Paper & Pen: Prepare yourselves to write queries and discuss strategies WITHOUT using a computer.
  • A Dash of Fun & Friendly Competition: Embrace the challenge with a positive and collaborative spirit!

The Challenge

This workshop will be divided into rounds, each presenting a unique SQL query challenge. The scenarios will target various SQL functionalities, so get ready to flex your SQL muscles.

You will write your answers on paper not on a computer. Close your laptops. You may use printed SQL CheatSheets to help you.

  • Round 1: Data Retrieval: Test your fundamental SELECT statement skills, filtering and retrieving specific data from a database table.
  • Round 2: Joining the Party: Level up the difficulty with JOINs, combining data from multiple tables to unlock hidden insights.
  • Round 3: Advanced Arena: Challenge yourselves with more complex queries, potentially involving functions, aggregations, or subqueries.

Bonus Round (Optional): Feeling confident? The quiz leader may throw in an extra round with a real-world database scenario, pushing your problem-solving abilities.

Acceptance Criteria

  • Participation is Key: Actively engage with your team, discussing questions and contributing ideas throughout the quiz.
  • Demonstrate SQL Skills: Work together to formulate correct and efficient SQL queries to solve the presented challenges.
  • Teamwork Triumphs: Collaborate effectively and communicate your solutions clearly within your team.

Bonus Point: If you tackle the bonus round, aim to deliver a well-structured and insightful solution that addresses the real-world scenario.

Let the Games Begin!

Get ready to unleash your SQL mastery and collaborate with your team to conquer the challenges. Remember, effective communication, teamwork, and a dash of friendly competition are the keys to success!

SQL Showdown: Team Quiz Extravaganza - Example Questions

Round 1: Data Retrieval 10 minutes

Scenario: You’re working with an e-commerce database.

Question 1: Say what you see

Write a query to select all product names and prices from the products table.

Question 2: WHERE are we going with this

How can you modify the query to only show products with a price greater than $50?

Round 2: Joining the Party 10 minutes

Scenario: The e-commerce database also has a table named orders that stores information about customer purchases. Each order references a product ID from the products table.

Question 1: Are you in on this

Write a query to retrieve the product name, price, and order quantity for all orders.

Question 2: Oh WHERE do we begin

Modify the query to only show orders for products with a price greater than $100.

Round 3: Advanced Arena 10 minutes

Scenario: Let’s add a customers table to the mix, containing customer names and their order IDs.

Question 1: Does this COUNT AS fun?

Write a query to find the total number of orders placed by each customer.

Question 2: Are we HAVING fun yet?:

How can you modify the query to show only customers who have placed more than 2 orders?

Bonus Round: Real-World Scenario

Scenario: The marketing team wants to identify the top 3 most popular products (by total quantity ordered) for a targeted campaign.

Challenge:

Write a query to achieve this, considering the tables: products, orders.

Remember: These are just examples. You can adjust the difficulty level and scenarios based on your group’s SQL knowledge and experience.

The winning team 🏆

Take a victory lap and eternal glory in the CodeYourFuture Hall of Fame. May the best SQL warriors emerge victorious! 🏆🔥

stand-up 🔗

  1. Split up into breakout rooms
  2. Take it in turns to describe something that is blocking you on the coursework. Try to be as specific as possible about the issue you’re having. See if you can find out the answer ( volunteers and trainees can provide guidance with this )

If both volunteers and trainees don’t know how to solve the problem then discuss where to go next. Where can you ask a question and in which channel?

template 🔗

Workshop Name

Replace this readme with the requirements for your workshop

Learning Objectives

Requirements

Explain the requirements of the workshop. You might want to talk about goals here. You might want to use formal specifications like Given/When/Then. It’s ok for requirements to be in different formats. We want trainees to learn to interpret requirements in many settings and expressions. Just make sure your workshop is active and not a lecture.

Always write your workshop in a readme.md in a folder with the same name as the workshop. This makes it easy to find and easy to show on the curriculum website.

Acceptance Criteria

  • I have provided clear success criteria
  • These might be related to the objectives and the requirements
  • I have given some simple, clear ways for trainees to evaluate their work
  • I have run Lighthouse and my Accessibility score is 100

testing 🔗

Why do we test?

How do you check if your code is working? You could test it manually, e.g.

function greet(name) {
  return `Hello ${name}`;
}

let name = "Ellie";

let result = greet(name);

console.log(`Expect ${result} to equal Hello Ellie`);
// Expect Hello Ellie to equal Hello Ellie

A simple console.log can verify that our code behaves correctly. But this approach isn’t very robust. What happens if I want to change my function?

function greet(name) {
  return `Hi ${name}`; // <-- I changed the greeting
}

let name = "Ellie";

let result = greet(name);

console.log(`Expect ${result} to equal Hello Ellie`);
// Expect Hi Ellie to equal Hello Ellie <-- I didn't change the console.log, so how do I know if my function is meant to greet with 'Hi' or 'Hello'?

Our console.log is helpful if we remember to check the output, but a testing tool, like Jest can tell us if our code works or not more clearly.

Why do we use automated tests?

  • You can be more productive because you don’t have to spend the as much time manually testing the code yourself
  • Tests allow you to make changes in your code quickly and safely without breaking the existing behaviour
  • Tests provide documentation for what your code is actually meant to do

Why do we use test driven development?

  • It helps us write better code. Code that can be easily tested tends to be cleaner and more modular
  • It helps us break down the problem into smaller chunks
  • It encourages us to think about edge cases (the less likely paths in our code)

Pair exercise

  • Use test driven development in pairs to complete this exercise

    • person A should write a failing test
    • person B should make the test pass by implementing the code
    • person A should refactor (if necessary)
    • then start again, this time person B writes the failing test
  • Write a function that

    • takes a number as an argument
    • returns a string of comma separated numbers from 1 to the number passed in
    • for every number that is divisible by 3, the number should be replaced by ‘fizz’
    • for every number that is divisible by 5, the number should be replaced by ‘buzz’
    • for every number that is divisible by both 3 and 5, the number should be replaced by ‘fizzbuzz’

Examples

Given 1, the function should return “1”.

Given 15, the function should return “1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz”.

Running the tests

cd testing

npm i

npm run test

time-string 🔗

formatSecondsAsString

Learning Objectives

When programming, you will often encounter large problems. Developers must learn to break down complex problems into smaller problems. In this workshop, we’ll use tests to break down the implementation of formatAsSecondsAsString.

Given a time in seconds,
When formatAsSecondsAsString is called with the time
Then we it should return a well formatted time string.

For example, if we call formatAsSecondsAsString with 390
then we should get “6 minutes and 30 seconds”

If we call, formatAsSecondsAsString with 6327894 then we should get ""

🧩 Break down the problem

(10 mins)

To break down this problem, we will only start considering seconds inputs <= 60. Why do you think this is a good place to start?

formatAsSecondsAsString(1) // "1 second" 
formatAsSecondsAsString(50) // "50 seconds" 

Spend 10 minutes, think about some other test cases you can explore to check this functionality

🧪 Set up tests

(10 mins)

In this directory (time-string), create a package.json and install Jest as you did in the prep material.
Next, create a test file, time-string.test.js. In there, write your first test.

🩺 First steps

(10 mins)

Once you’ve written your first test, you’ll need to implement the logic to get it working for this test case. Don’t try rushing ahead in this kata - otherwise it could become very unwieldy!

💼 New cases

Now we’ll consider cases where the input is less than 3600? Why is this a good idea?

formatAsSecondsAsString(61) // "1 minute and 1 second" 

Continue this pattern of writing tests and then implementing your functionality. Do this until you’re confident your function works in the case where the input is less than

touch-typing 🔗

Why is typing important?

first 10 minutes

Short presentation where Jonathan shows how much of a nerd he is about typing and keyboards

see presentation.pdf for slides

second 25 minutes

Everyone practice on https://www.typingclub.com

try to get to lesson 10, and further if you can

last 15 minutes

Within your study groups, compete on https://www.typeracer.com and nominate your champion

press “Create Racetrack” under “Race your friends”

The champion of each group will compete in a final to become GRAND CHAMPION

triangles 🔗

Learning objectives

🧰 Setup

In this workshop, you’ll need to:

  1. Split up into groups of 4

Context

To begin, you’ll need some context.

Use this page 👉 https://www.mathsisfun.com/triangle.html to get the names of different triangles depending on their three side lengths.
There should be 3 different names. Check with each other that you all understand what these names mean.

Problem statement

In this workshop, you’ll need to implement a function that takes the three side lengths of a triangle and returns a string indicating whether it is "equilateral", "isoceles" or "scalene"

Acceptance criteria

First, name the function according to the problem statement. The name should be semantic. It should convey what the function does.
Then set out acceptance criteria for your function in the format shown below:

Given
When
Then

🧪 Write your first assertion

Write your first assertion using console.assert to check the functionality. You can write your code in triangles.js

🧱 Start building up your functionality

Once you’ve got your first assertion down, you’ll need to start building out your functionality for this case.

undefined 🔗

Group Exercise

  • Split into groups of 3 or 4.
  • For each example in this section - discuss the code as a group.
  • Why does the output in each example contain undefined?
  • Try each code example in VSCode
  • Can you change something so it no longer outputs undefined?

wordle 🔗

Wordle CLI Workshop

This is a workshop where we, as a class, build a Wordle CLI clone in Node JS.

Learning Objectives

Requirements

  • Split the cohort into groups of 3 to 4 people
  • We start with an energiser where we play an actual game of Wordle (https://www.nytimes.com/games/wordle/index.html) - sourcing guesses from the class, and hopefully learning how the game works in the process
  • Ensure the class understands the rules of the game first
  • Then we start building out our Wordle CLI clone from scratch
    • Referencing steps from this README: https://github.com/CodeYourFuture/wordle-clone-example#readme (this example solution can be given to the trainees after the session has finished)
    • Steps 1 & 2 can be done together as a class. All the code here should be sourced from the trainees themselves - this is their implementation. However, the volunteer who is running the workshop can ensure the high-level problem is broken down into these smaller functions: getRandomWord, getGuess and showWordWithHighlights
    • Step 3 (getRandomWord) can be done in groups
    • Step 4 (getGuess) can be done in groups - but it might be useful for a volunteer to suggest which NPM dependency we could use
    • Step 5 (showWordWithHighlights) can be done in groups - again, we can suggest which NPM dependency to use
    • Step 6 (improving the user experience) could possibly be done as a class together

Acceptance Criteria

Given the user starts a new Wordle game
When the app is initialized
Then a random 5 letter word should be selected as the target word

Given the target word has been selected
When the user enters a 5 letter guess
Then the guess should be validated
And each letter should be marked as green, yellow or gray based on whether it matches the target word

Given a valid 5 letter guess has been entered
When the guess does not match the target word
Then each letter should be marked as follows:

  • Green if the letter is in the correct position
  • Yellow if the letter is in the target but not in the correct position
  • Gray if the letter is not in the target word

Given a guess has been submitted
When the guess matches the target word
Then a message should indicate the user has won the game

Given guesses have been submitted
When the user reaches 6 guesses without matching the target word
Then a message should indicate the user has lost and show the target word

  • I understand the code I have written