diff --git a/breaking-down-quote-app/README.md b/breaking-down-quote-app/README.md
new file mode 100644
index 00000000..f6f17766
--- /dev/null
+++ b/breaking-down-quote-app/README.md
@@ -0,0 +1,117 @@
+# Breaking down the quote generator
+
+You should have already followed the prep to design, write, and deploy a quote generator.
+
+We already broke down this project into steps. We're going to talk about the techniques that helped us to do this breaking down. This will help you to break down projects yourself in the future.
+
+Get into groups of about 5, with at least one volunteer per group.
+
+## Axes to break down by (20 minutes)
+
+There are different ways we can break down a project. For instance:
+* We could write the whole frontend, then the whole backend (or the whole backend then the whole frontend).
+* We could build one entire feature in the frontend and backend, then another feature in the frontend and backend.
+* We could write down the whole API between the backend and frontend, and then build one, then the other.
+
+There are other ways we could break down the project too.
+
+Spend 3 minutes thinking of different ways you could break down a project.
+
+Spend 10 minutes discussing all of your ideas (including the suggestions above) in your group. What advantages does each approach have? What disadvantages does each have?
+
+Are the answers different depending on the number of people working on the project?
+
+Are the answers different depending on whether you have specialists (e.g. one person who is specialised in frontend and one specialised in backend) vs generalists (people who can do a bit of everything)?
+
+Can you think of ways to combine approaches, to get the advantages of different approaches?
+
+
+
+Hints for volunteers
+
+We're generally trying to get towards:
+* Breaking down by feature is useful (proves out end-to-end design, provides incremental value, ...).
+* Thinking about data / APIs can help us to develop components in parallel.
+* We can often interact with components in isolation for testing, e.g. `curl` testing against a backend, dummy backends for testing frontends, etc.
+
+
+## User journey mapping
+
+### Collecting features (5 minutes)
+
+We often first break down projects by feature. We try to build entire end-to-end journeys for one thing a user can do at a time.
+
+One example of a feature our quote generator has is "Add a quote".
+
+Spend 2 minutes thinking of as many features as you can for our quote generator. These don't have to be things we _have_ implemented, they can also be things we _haven't implemented yet_. For instance, I can imagine after adding a quote, a user may want to share a link to _that_ quote with someone - our server doesn't support this right now (it only shows random quotes). But this is still a feature we can imagine.
+
+In your group, make a list of all of the features you have thought of.
+
+
+
+Some examples if you're really stuck
+
+* Displaying a quote on first load.
+* Displaying new quotes on demand.
+* Adding new quotes.
+* Seeing the quote you just added actually got added.
+* Sharing a link to a specific quote.
+* Displaying a new quote that is guaranteed not to have been show before.
+* Showing statistics about how often a quote has been displayed.
+* Up/down-voting quotes.
+* Finding quotes on similar themes.
+* Listing all of the quotes by a particular person.
+* Auto-grouping similar quote authors (e.g. "FDR" and "Franklin Roosevelt" are the same person).
+
+
+
+### Mapping features (20 minutes)
+
+Pick three features and create user journey maps for them. Use [the user journey mapping intro you read](https://www.nngroup.com/articles/journey-mapping-101/) to help you - who wants to use each feature? What do they want to achieve? What steps would they need to achieve their goals? What would they experience on the way?
+
+## Making a plan
+
+### Unlocking parallelism and feedback (10 minutes)
+
+When developing, we want to get feedback as quickly as we can. We don't want to have to build a whole backend and a whole frontend and a whole database in order to see whether any one piece works.
+
+It can be helpful to think about the _interfaces_ between these components before building them. Asking questions like:
+* For each operation, what data will we need to pass from the frontend to the backend?
+* For each operation, what data will we need to pass from the backend to the frontend?
+
+In our quote generator, this may mean asking questions like:
+* What information does the frontend need from the backend in order to display a quote? (The answer here may be: An object containing two fields - the quote as a string, and the author as a string).
+* What information does the frontend need to give the backend to save a quote?
+* What information does the frontend need to give the backend in order to get a specific quote? (This question may suggest we need some kind of ID for each quote, which we can put in a URL, but don't show to the user in the page).
+* What information does the frontend need to give the backend if it wants to guarantee the next quote it shows hasn't been shown to this user before?
+
+For each of the three features your have mapped, write down what information needs to be sent between which components in order to perform an action. Be specific. Include names and types of each field.
+
+### Agreeing on data formats and APIs
+
+Now that we know what data we need to pass where, we can come up with the APIs we need to build. This can happen at multiple levels, e.g. you can decide:
+* The backend APIs your frontend will call (and what the requests and responses will look like).
+* The function one part of your frontend will call to to generate a component for some data.
+* The frontend URLs that a user can visit to interact with the application, and what they will do.
+* And more.
+
+By agreeing on these things, we can start building them in parallel - one person can be working on one side of the API (like the backend endpoint, or a function) while another works on the code that will call it.
+
+### Using dummy data
+
+We can even use fake versions of these APIs with dummy data.
+
+One of our user journeys is "When I load the page, a quote is displayed". Some ways we can develop this without having a whole backend:
+* We can write the frontend code to display a quote with one hard-coded quote.
+* We can write a `fetchQuote` function in the frontend which doesn't call a backend but instead always returns one quote _in the data format we've agreed_.
+* We can fetch a quote, but write a small backend where the "get quote" endpoint always returns one quote (while someone makes the backend do something more complicated like choose a random quote).
+
+These are all ways we can develop and test our frontend before completing the whole system. Agreeing on a data format, and APIs, makes it easier for us to do this.
+
+### Making a plan (30 minutes)
+
+For each of the three user journey maps you've created, make a plan for how you could break these down and implement them.
+
+You should work out the data formats, work out the APIs, and work out how different people could be working on different parts of the implementation at the same time.
+
+Write down tickets for each task that contain enough information that someone could pick up the ticket and work on it. Make sure to identify which tickets _depend_ on which other tickets (i.e. which ones need to be done before each other).
diff --git a/devtools/readme.md b/devtools/readme.md
index 71deed4d..c11b6b53 100644
--- a/devtools/readme.md
+++ b/devtools/readme.md
@@ -157,15 +157,6 @@ So we've explored the Elements panel, the Styles panel, and the Lighthouse panel
For example, you have just looked in the Elements panel. This is not really your HTML, this is [the DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction), 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](https://developer.mozilla.org/en-US/docs/Web/API) it builds. Let's look at another one right now!
-
-
-1. Set a [timer for 5 minutes](https://www.google.com/search?q=timer+for+5+minutes).
-1. Find the [Accessibility Panel](https://developer.chrome.com/blog/full-accessibility-tree/) and check 'Enable full-page accessibility tree'
-1. Now click the "Universal Man" button in the Elements Panel.
-1. What is _Ignored_ in the Accessibility Tree that is present in the DOM?
-1. When the timer goes off, share your answer with the other groups by pasting in the workshop thread.
-
-
### Reflect
diff --git a/dom-merge-conflict/tasks/buttons-and-counter/src/app.js b/dom-merge-conflict/tasks/buttons-and-counter/src/app.js
index af608eb6..f38eb4c7 100644
--- a/dom-merge-conflict/tasks/buttons-and-counter/src/app.js
+++ b/dom-merge-conflict/tasks/buttons-and-counter/src/app.js
@@ -3,6 +3,10 @@ function increment(node) {
let current = node.textContent;
node.textContent = Number(current) + 1;
}
+function decrement(node) {
+ let current = node.textContent;
+ node.textContent = Number(current) - 1;
+}
export function App() {
const body = document.createElement("body");
@@ -10,7 +14,8 @@ export function App() {
const header = document.createElement("header");
header.innerHTML = `
Number Counter
-
A simple counter. Press increment to increase the count by one.
+
A simple counter. Press increment to increase the count by one. Press decrement to decrease by
+
+
`;
body.appendChild(main);
const button = body.querySelector("#increment");
+ const buttonDecrem = body.querySelector("#decrement");
const counter = body.querySelector("#counter");
button.addEventListener("click", () => {
increment(counter);
});
+ buttonDecrem.addEventListener("click", () => {
+ decrement(counter);
+ });
+
return body;
}
diff --git a/dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js b/dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js
index 1139e456..73452c05 100644
--- a/dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js
+++ b/dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js
@@ -35,7 +35,7 @@ describe("button and counter", () => {
expect(getByTestId(container, "counter")).toHaveTextContent(/^2$/);
});
- describe.skip("decrement button", () => {
+ describe("decrement button", () => { ///.skip removed
test("pressing Decrement decreases the counter", () => {
const button = getByRole(container, "button", {
name: "Decrement",
diff --git a/error-handling/readme.md b/error-handling/readme.md
new file mode 100644
index 00000000..02094767
--- /dev/null
+++ b/error-handling/readme.md
@@ -0,0 +1,69 @@
+# Error Handling
+
+## Learning Objectives
+
+```objectives
+- [ ] Give examples of good and bad error messages
+- [ ] Explain what makes an error message helpful
+```
+
+## Understanding What Went Wrong
+
+We have already seen examples of developer questions which can help us fix problems in our code:
+
+1. What I _did_
+2. What I _expected_
+3. What actually _happened_
+
+The problem is that figuring out what happened can be really tricky if the developer writing the code doesn't do a good job of **error handling**. In this workshop we're going to discuss error messages, why they are important and what makes some more helpful than others.
+
+What makes an error message "good" depends on who it is intended for. For example, the runtime errors you may have seen while working through the exercises are great for developers while they're working on the code but they aren't very useful for the end user looking at an app on their phone. Knowing the most appropriate way to communicate problems is a key skill for a developer.
+
+### Setup
+
+- **Trainees**: Go to the `error-handling` folder in the [Workshops repo](https://github.com/CodeYourFuture/CYF-Workshops/), navigate to the `webpage` folder and open `index.html` in a browser.
+- **Trainees**: Work in groups of 2 or 3.
+- **Trainees**: Nominate a member of the group to take notes.
+- **Volunteers**: Nominate someone to facilitate the group discussion. This could be a volunteer or a trainee.
+
+
+
+Open your web browser and take a look at the web page you just opened. You should see a text box with five buttons below it. When you type a message and press any of the buttons it should appear below the box. Try it out by typing "hello world" and see what happens.
+
+The problem we have is that none of the buttons seem to be working! They all have the same problem but they aren't all telling us the same thing. We could probably open `script.js` and easily figure out where the problem is, but this won't be an option for the end users of our code.
+
+In your groups, **without looking at the code**, answer the following questions for each button:
+
+1. Can you find where the error message is being displayed? (Hint: there may not always be an error message)
+2. Can you figure out what the problem is based on what the message is telling you?
+3. Does the message tell you how to fix the problem?
+4. Is the message more useful for a developer or a user?
+
+
+
+
+
+Come back together to compare notes. As a group try to answer these questions:
+
+1. Which buttons gave useful error messages? Which buttons weren't helpful?
+2. Which button gave the clearest error message?
+3. Which features of the messages were particularly useful for **developers** and which features were useful for **users**?
+4. How could the messages be further improved for users?
+
+
+
+## Supporting the User
+
+We have seen that communicating what went wrong is really important when building an application. Giving feedback to the user is useful, but how we give that feedback is important. We could improve the user experience even more by helping them avoid the problem altogether!
+
+
+
+Read [this article](https://piccalil.li/blog/how-to-write-error-messages-that-actually-help-users-rather-than-frustrate-them/) on writing helpful error messages. Think about the error messages we have seen so far - do they align with the suggestions made here?
+
+It would be even better if we never needed to show our users any error messages, but that won't happen if we aren't clear about what we need them to do. Take another look at the application from the first part of this workshop and answer these questions:
+
+1. What information is missing that might help the user?
+2. How can we let the user know what the requirements are before they start typing?
+
+
+
diff --git a/error-handling/webpage/index.html b/error-handling/webpage/index.html
new file mode 100644
index 00000000..4b1f3f94
--- /dev/null
+++ b/error-handling/webpage/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+ Broken Buttons
+
+
+
+
Broken Buttons
+
+
+
Enter some text in the box below then click one of the buttons.
+
If everything works your message will be added below the box.
+
+
+
+
+
+
+
+
+
You typed:
+
+
+
\ No newline at end of file
diff --git a/error-handling/webpage/script.js b/error-handling/webpage/script.js
new file mode 100644
index 00000000..c9bff740
--- /dev/null
+++ b/error-handling/webpage/script.js
@@ -0,0 +1,58 @@
+const textarea = document.querySelector("#submission");
+const silentFailButton = document.querySelector("#silent-fail-button");
+const consoleButton = document.querySelector("#console-button");
+const poorAlertButton = document.querySelector("#poor-alert-button");
+const devAlertButton = document.querySelector("#dev-alert-button");
+const betterAlertButton = document.querySelector("#better-alert-button");
+const outputArea = document.querySelector("#output");
+
+const validateMessage = (message) => {
+ return message.length >= 250;
+}
+
+const appendMessage = (message) => {
+ outputArea.textContent = message;
+}
+
+silentFailButton.addEventListener("click", () => {
+ const message = textarea.value;
+ if (validateMessage(message)) {
+ appendMessage(message)
+ }
+})
+
+consoleButton.addEventListener("click", () => {
+ const message = textarea.value;
+ if (validateMessage(message)) {
+ appendMessage(message)
+ } else {
+ console.error("Invalid message - check failed at script.js:10")
+ }
+})
+
+poorAlertButton.addEventListener("click", () => {
+ const message = textarea.value;
+ if (validateMessage(message)) {
+ appendMessage(message)
+ } else {
+ alert("Something went wrong")
+ }
+})
+
+devAlertButton.addEventListener("click", () => {
+ const message = textarea.value;
+ if (validateMessage(message)) {
+ appendMessage(message)
+ } else {
+ alert("Failed with error code 03986")
+ }
+})
+
+betterAlertButton.addEventListener("click", () => {
+ const message = textarea.value;
+ if (validateMessage(message)) {
+ appendMessage(message)
+ } else {
+ alert(`Message must be at least 250 characters long - yours was ${message.length}. Please try again`)
+ }
+})
\ No newline at end of file
diff --git a/explaining-code/README.md b/explaining-code/README.md
new file mode 100644
index 00000000..e045a112
--- /dev/null
+++ b/explaining-code/README.md
@@ -0,0 +1,61 @@
+# Explaining code
+
+## Learning objectives
+
+```objectives
+- [ ] Make a strategy for how to explain code.
+- [ ] Explain the big picture (what not how) of a software system.
+- [ ] Explain how functions and lines of code in a software system work.
+```
+
+We often need to explain our code to others. Some examples of when we need to do this:
+1. When someone else is going to start working on it with us.
+2. When trying to get help with our code from someone else.
+3. In a job interview.
+
+Pick a project you've been working on recently to explain. The project doesn't need to be complete, but it should be at least 100 lines of code and should take more than a couple of sentences to explain.
+
+## The big picture (15 minutes)
+
+Start by introducing the big picture of the code:
+- What is the project?
+- What problem does it solve?
+- How does the program generally work?
+
+Do this before digging into specifics (e.g. what a function does, what some lines do).
+
+5 minutes: On your own, think about how you will explain the big picture of a project. What is useful for someone to know? In what _order_ is it useful to introduce those ideas? Once you have an idea, try thinking through how you would explain the project you've chosen.
+
+Volunteers: Facilitate this discussion:
+
+10 minutes: Discuss as a whole class your ideas for how to introduce the big picture of a project. At the end of this discussion, you should have a template of a script with the different topics you would explain.
+
+## Explaining specific code (15 minutes)
+
+5 minutes: On your own, think: how would you like a new codebase to be explained to you? Some things to consider:
+* Where would you want the explainer to start?
+* Would you want to go depth first (keep following all of the function calls before you move into the next line) or breadth first (read each line of a function, before looking at the functions it calls)?
+* What kind of example data may be useful to consider?
+* Is it more interesting to focus on normal cases or unusual cases (e.g. errors)?
+
+Volunteers: Facilitate this discussion:
+
+10 minutes: Discuss as a whole class your ideas for how to walk through specific code. At the end of this discussion, you should have a template of a script with the different topics you would explain.
+
+## Walk through (50 minutes)
+
+Split into pairs (and a group of three if needed).
+
+Imagine you are in a job interview, explaining your project to an interviewer. The interviewer doesn't know anything about your project.
+
+Take turns to explain your chosen project codebase to your partner. Use the frameworks you established earlier in the workshop. At the end of your explanation, your partner should be able to talk about and explain the code you showed them. Feel free to ask/answer questions on the way.
+
+Make sure that each partner has an equal time to explain their codebase.
+
+Volunteers: Observe different groups explaining code. Feel free to ask questions or give feedback as you do.
+
+## Wrap up (10 minutes)
+
+As a whole class, discuss your experience. What techniques did people use that helped make things clear? When were you confused? What could people have done differently?
+
+How will you explain things differently next time?
diff --git a/interview-introductions/readme.md b/interview-introductions/readme.md
new file mode 100644
index 00000000..0391ca5a
--- /dev/null
+++ b/interview-introductions/readme.md
@@ -0,0 +1,57 @@
+# Interview Introductions
+
+Before starting this workshop, you should have reviewed the interview introductions prep item.
+
+For this workshop you need to break up into groups of 3-4 trainees, each with at least one volunteer. We will be trying to make some sample introductions for Jane.
+
+Jane is a fictional person who has completed a software development programme. Jane is applying for a Junior Software Developer role with the fictional company, Software for Lawyers Ltd. You donβt need to understand all of the technical terms in these two pieces of text to complete the task.
+
+```objectives
+- [ ] Tailor an introduction to job requirements
+- [ ] Describe what makes an introduction engaging or boring
+- [ ] Deliver an introduction out-loud
+```
+
+
+
+In small groups, ideally with a volunteer in each group if possible.
+
+1. Set a [timer for 5 minutes](https://www.google.com/search?q=timer+for+5+minutes).
+
+2. Read through the summary of Jane's background and the job description
+
+3. Set a [timer for 10 minutes](https://www.google.com/search?q=timer+for+10+minutes).
+
+4. Individually, write an introduction for Jane to be used for her interview with Software for Lawyers Ltd. You should be aiming for it to be 1-2 minutes long which is approximately 140-300 words. Volunteers can join in with this if they want.
+
+5. In your groups, take turns reading out your introductions for Jane. Give eachother feedback. Everyone in the group should give feedback about every introduction. Try to put yourselves in the shoes of the hiring manager. Does their introduction give the impression that Jane is a perfect fit? If not why not? What differences are there between your introductions? Which ones make you want to work with Jane? Why?
+
+6. If you have time, try making an introduction for yourself and share it with the group
+
+
+
+### Janeβs summary
+Jane has recently completed the part time Super Coders Software Development programme. During this time, she was also working full-time and caring for her two children. The course teaches full stack web development and general programming concepts. It teaches HTML, CSS, JavaScript, Node.js, Express, React and PostgreSQL.
+
+Jane is very passionate about programming. She taught herself the Python programming language before starting the course.
+
+Her portfolio includes many full stack applications. This includes projects she has built with other students, as well as some solo projects. Sheβs especially proud of a project called Pin the Mood. This project stores book recommendations until the user has time to read the books. The project used React, Express, Node.js and PostgresSQL. The project team was an agile team made up of two trainees, a scrum master and a tech lead.
+
+After leaving school seven years ago, she joined Lawyers 4U as a call handler. She has developed excellent interpersonal skills and has gained experience working under pressure.
+
+### The Job Description
+Software for Lawyers Ltd makes case management software. Their software helps lawyers manage caseloads and track time spent. The development team is small and close knit. They are looking to add a Junior Software Developer to their team.
+
+**Requirements**
+* A university degree in a relevant subject or a software development course
+* Experience with Node.js, Express and React
+* A strong portfolio with solo and group projects
+* Excellent interpersonal skills
+* Experience developing software in an agile team
+* Passionate about programming
+
+**Nice to Haves**
+* Experience in the legal sector
+* Some knowledge of Python
+* Experience working in an office-based environment
+
diff --git a/jobs-in-tech/README.md b/jobs-in-tech/README.md
new file mode 100644
index 00000000..afa4e895
--- /dev/null
+++ b/jobs-in-tech/README.md
@@ -0,0 +1,75 @@
+# Your First Job in Tech
+
+## Learning objectives
+
+```objectives
+- [ ] List at least 3 common entry-level roles in tech, what they entail, and their necessary skills
+- [ ] Take the first actionable steps toward a career in tech.
+- [ ] Describe your plan about your own career in tech
+```
+
+## What jobs are available in the tech industry?
+
+Some of your will become software developers. It's a great path, but there are also other great jobs in the tech industry. So let's work together in understanding the different roles out there.
+
+### Let's do some research
+
+1. Make pairs or small groups of 3-4. Research what jobs are available in tech industry. You can also use these [CompTIA Career Pathways](https://www.comptia.org/en/explore-careers/job-roles/?page=1&category=all) or
+[TechCareerExplorer](https://www.careerexplorer.com/careers/?industry=42) as reference. Each group should chose one of these families of roles to research:
+- Engineering roles
+- Low code roles
+- Tech jobs without coding
+- IT jobs
+
+Write 1 role per post it. (10 min)
+
+2. Choose a wall (or, if online, use a Miro board or similar), and walk through each post it. See if you can explain the role - and if you can't, ask if anyone in the group can. (15 min)
+
+3. Pick one role from each group and let's identify more about it: (15 min)
+ π― Job Title \
+ π§ What do they actually do all day? \
+ π¬ Tools or software they use (Google it!) \
+ π How to get this job: Degree? Certifications? Courses? \
+ π Skills needed (soft and hard) \
+ π Find a real job post and copy 1 key requirement
+
+4. Present the role back to the group.
+
+
+
+Hint for volunteers
+
+Make sure we've covered:
+
+* Engineering roles: Software developer, Quality Engineer, Site Reliability Engineer
+* Low code roles: Low-code Dev and No-code Dev, Wordpress Developer, Database administrator
+* Jobs in tech without coding: Scrum Master, Manual tester, Business Analyst,
+* IT Jobs: IT Analyst, IT Support
+
+
+
+
+## Which one is for me?
+
+As we said in the start of this workshop, software developer is one of the many paths in the tech. And CodeYourFuture wants to support you in your chosen career.
+
+
+
+Hint for volunteers
+
+Focus on transferable skills and new skills, as well as what is their reality and availability to get ready for it
+
+
+
+Get together in pairs and talk about your own career path considering what you learned today. Use the below scripts to reflect on (5 min)
+- What are your good professional skills, the ones everyone always praises you about?
+- From the roles we discussed, which one are you most interested and why?
+- What will be your next steps to focus on getting this role?
+- What will be the blockers I will have?
+
+Write down your career action plan, which you can discuss further with your Career mentor:
+- πΌ Job I want to explore more:
+- π Skills I need to learn:
+- π Free resources Iβll start with:
+- π§βπ€βπ§ A person/community Iβll reach out to:
+- π 3 Things Iβll do this week:
\ No newline at end of file
diff --git a/prioritisation-and-estimating/README.md b/prioritisation-and-estimating/README.md
new file mode 100644
index 00000000..2aebc1c2
--- /dev/null
+++ b/prioritisation-and-estimating/README.md
@@ -0,0 +1,128 @@
+# Prioritisation & Estimation
+
+## Introduction to Prioritisation (20 mins)
+
+Your objective in this section is to understand why prioritisation matters in software development.
+
+1 minute: Individually, think of as many reasons as you can that prioritisation matters in software development.
+
+4 minutes: Go around the group sharing these reasons.
+
+
+
+Hint for volunteers
+
+Make sure we've covered:
+
+* Teams can't build everything at once due to time, budget, and resource constraints.
+* There are different ways we can prioritise the features, refer to pre-reading required for the class.
+* Prioritisation frameworks like Value vs. Effort help focus on high-impact features.
+
+
+
+Activity (15 mins): Form groups of about 3 and discuss following:
+
+* 5 mins: Individually review [the suggested features in chat app backlog](https://sdc.codeyourfuture.io/decomposition/sprints/2/prep/#chat-application-requirements) (e.g., message reactions, scheduled messages, formatting, replies). Feel free to add your own suggestions too.
+* 10 mins: Write responses for following questions and discuss within your group:
+ 1. How would you decide what to build first?
+ 2. What would your prioritisation methodology be based on?
+ 3. Which features do you think a software development team at WhatsApp prioritised in their first 6 months?
+
+## Value vs. Effort Matrix Explained (10 mins)
+
+
+
+Hint for volunteers
+
+Make sure we emphasise that the Value vs. Effort framework is one of the most commonly used frameworks for beginner level product development teams and cover below aspects of the Framework.
+
+
+
+* **Value**: Benefits to users or business (e.g. user satisfaction, revenue).
+* **Effort**: Time, complexity, and resources required.
+* **Quadrants**:
+
+| | Low Value | High Value |
+| :---- | :---- | :---- |
+| Low Effort | ***Maybes*** | ***Quick Wins*** |
+| High Effort | ***Time Sink*** | ***Big Bets*** |
+
+Example:
+
+* *Quick Win*: Adding emoji reactions (high value, easy to implement).
+* *Time Sink*: Custom animated avatars (low value, complex).
+
+## Group Exercise: Feature Prioritisation (40 mins)
+
+### Step 1: Review Features (5 mins)
+
+In your groups of about 3, spend the next 5 mins shortlisting 8β10 features from your initial features list. Find some examples below:
+
+1. End-to-end encryption
+2. Message editing
+3. Group video calls
+4. User profile customisation
+5. Message search
+6. Chat history backup
+7. Read receipts
+
+### Step 2: Score Features (20 mins)
+
+* 10 mins: Rate each feature's value (1β5 scale) and effort (1β5 scale).
+* 10 mins: Plot them on a matrix (use whiteboards or printed templates or Mural).
+
+
+
+Hint for volunteers
+
+Make sure all teams understand the matrix has value on one axis and effort on the other.
+
+
+
+Use below guiding questions to rate the features' value and effort:
+
+* Value: How many users will benefit? Does it solve a core problem?
+* Effort: How many developer hours would each feature take? Are there technical risks?
+
+### Step 3: Debate & Finalise Priorities (15 mins)
+
+
+
+Hint for volunteers
+
+Teams must agree on quadrant placements.
+
+
+
+In your groups of about 3, discuss following:
+
+* 4 min: Which 2β3 features would you build first? Why?
+* 4 min: What features are overlapping? Why? How may that impact our choices?
+* 4 min: Which features depend on other features development?
+* 3 min: Which features will we likely _never_ build?
+
+## Group Presentations & Discussion (15 mins)
+
+5 mins presentation time per group: Select one person to present your decisions. Share your group's matrix and top priorities.
+
+Discussion points for presenters from each group:
+
+* Did your team disagree on scoring? How did they resolve it?
+* What assumptions did you make about users or technical constraints?
+* Would you deprioritise a high-value feature if it's too complex? Why?
+
+## Reflection & Takeaways (5 mins)
+
+Popcorn around the class and share your key takeaways from this workshop.
+
+
+
+Hint for volunteers
+
+Ensure the below points are emphasised:
+
+* Prioritisation forces trade-offs.
+* You can't build everything.
+* Quick wins build momentum; time sinks must be avoided..
+
+
diff --git a/sorting-cards/README.md b/sorting-cards/README.md
new file mode 100644
index 00000000..761377ee
--- /dev/null
+++ b/sorting-cards/README.md
@@ -0,0 +1,128 @@
+# Sorting Cards
+
+## Learning objectives
+
+```objectives
+- [ ] Analyse the actual cost (comparisons + swaps) of particular sorting algorithms.
+- [ ] Categorise different sorting algorithms by computational complexity.
+- [ ] Identify when different sorting algorithms are suitable.
+- [ ] Devise a specialised sorting algorithm for specific kinds of data.
+```
+
+## Outline
+
+You will need a deck of cards for this workshop per group.
+
+Split into groups of no more than 4 people.
+
+We are going to try sorting some cards using different algorithms to compare them.
+
+You will do a few different analyses over each algorithm:
+
+Shuffle the deck of cards and pick 13 random cards.
+
+## Algorithms (45 minutes)
+
+For each algorithm, in order perform the following steps:
+1. Predict its worst-case computational complexity (number of comparisons and swaps performed).
+2. Predict what order of cards you think would give the _best_ performance for the algorithm.
+3. Predict what order of cards you think would give the _worst_ performance for the algorithm.
+4. Shuffle the cards and perform the algorithm on them manually.
+5. Arrange the cards in the best and worst performances you predicted, and perform the algorithm on them manually.
+6. Compare your predictions with your observations.
+
+### Bubble sort (20 minutes)
+
+Bubble sort keeps going through the whole list, checking whether each pair of elements is correctly sorted. If not, it swaps them. It keeps going through the list over and over again until it's sorted.
+
+Because the highest/lowest element "bubbles" to the top in each loop, the highest/lowest encountered in each loop will be in it's correct place at the end of the loop. Each subsequent loop only needs to loop over the remaining unsorted elements (i.e. one less than the previous loop).
+
+Pseudocode (from Wikipedia):
+
+```
+function bubble_sort(A : list of sortable items)
+ n := length(A)
+ repeat
+ swapped := false
+ for i := 1 to n-1 inclusive do
+ if A[i-1] > A[i] then
+ swap A[i-1] and A[i]
+ swapped := true
+ end if
+ end for
+ n = n - 1
+ until not swapped or n == 1
+end function
+```
+
+### Insertion sort (10 minutes)
+
+Insertion sort treats a subset of the array as sorted (initially just one element), and each time removes a new element, finds its correct location in the sorted subset, and _inserts_ it there.
+
+Pseudocode (from Wikipedia):
+
+```
+function insertion_sort(A : list of sortable items)
+ i := 1
+ while i < length(A)
+ j := i
+ while j > 0 and A[j-1] > A[j]
+ swap A[j] and A[j-1]
+ j := j - 1
+ end while
+ i := i + 1
+ end while
+end function
+```
+
+### Merge sort (15 minutes)
+
+Merge sort splits all of the input into one-element sub-lists. It then takes pairs of those sub-lists and merges them in-order so that each merged list is sorted. It keeps merging those (increasingly large) sub-lists until there's one list, which will be sorted.
+
+Pseudocode (from Wikipedia):
+
+```
+function merge_sort(A : list of sortable items)
+ // Base case. A list of zero or one elements is sorted, by definition.
+ if length of A β€ 1 then
+ return A
+
+ // Recursive case. First, divide the list into equal-sized sublists
+ // consisting of the first half and second half of the list.
+ // This assumes lists start at index 0.
+ left := A[..(len m / 2)] // From the start excluding the m/2th element.
+ right := A[(len m / 2)..] // From the m/2th element to the end, including the m/2th element.
+
+ // Recursively sort both sublists.
+ left := merge_sort(left)
+ right := merge_sort(right)
+
+ // Then merge the now-sorted sublists.
+ return merge(left, right)
+end function
+```
+
+## Comparing the algorithms (15 minutes)
+
+Discuss:
+1. Which algorithm performed better for your randomly shuffled data?
+2. Which has the best worst-case complexity?
+3. When would each algorithm make sense to use in real life?
+
+## Sorting one suit (30 minutes)
+
+Instead of picking 13 random cards, pick all 13 cards from one suit, so that each card has a unique number.
+
+The best worst-case we've seen so far is worse than `O(n)`.
+
+Try to devise an algorithm for sorting these 13 cards which is `O(n)`. If you do, explain to the group why it's `O(n)`, explaining what properties of the cards you're relying on to get this performance. Demonstrate this bound by sorting some cards.
+
+
+
+Facilitation hints
+
+We're aiming for pigeonhole sort or counting sort here. Because we know the values are unique and contiguous, we know what the correct position is for each card (the ace should be in index 0, the 2 in index 1, the 3 in index 2, etc), so don't need to perform any comparisons at all - just insert each value into its correct place.
+
+This generalises to data where there's a known (e.g. uniform) distribution of values, such as a whole deck of cards. In less precisely controlled distributions, we may not know _exactly_ the destination position for values, but if we can guess well enough, we can do a broad pigeonhole/counting sort and then a few smaller comparison sorts of buckets.
+
+
diff --git a/technical-interviews/README.md b/technical-interviews/README.md
new file mode 100644
index 00000000..1422a766
--- /dev/null
+++ b/technical-interviews/README.md
@@ -0,0 +1,72 @@
+# Technical interviews
+
+## Learning objectives
+
+```objectives
+- [ ] Perform a technical interview.
+- [ ] Explain what you're thinking when solving a problem.
+- [ ] Write code in front of someone in an interview setting.
+```
+
+You will be applying for jobs, many of which require doing a technical interview.
+
+You should already have [read about technical interviews](https://sdc.codeyourfuture.io/guides/employability/interview/technical-interview-prep/). You should also have done an interview where you explained code in the Piscine. In this workshop, you'll be practising interviewing and being interviewed about technical content.
+
+Below is a list of interview questions. You should have decided with your partner which question you are asking before coming to class, and should have prepared for it. Do not look at, or prepare for, any of the other questions.
+
+## Interview questions
+
+* [Is it a Set?](https://www.codewars.com/kata/5fddfbe6a65636001cc4fcd2)
+* [Look and say numbers](https://www.codewars.com/kata/53ea07c9247bc3fcaa00084d)
+* [Mix fruit juice](https://www.codewars.com/kata/5905871c00881d0e85000015)
+* [Multiples of 3 or 5](https://www.codewars.com/kata/514b92a657cdc65150000006)
+* [FizzBuzz Backwards](https://www.codewars.com/kata/59ad13d5589d2a1d84000020)
+
+## Preparing to interview someone
+
+Think about your goals as an interviewer. You want to:
+* See the best someone can do - you're not trying to trick them.
+* Work out how they approach problems:
+ * Do they make a plan?
+ * Do they think about edge cases?
+ * How do they handle not knowing how to do something?
+ * How easy are they to help?
+* Can they solve the problem?
+* Can they reason about their code?
+* Do they run through their code with examples to test it?
+
+To do this you will need to:
+* Already know a good solution to the problem (ideally multiple solutions!)
+* Prepare how you're going to explain the problem
+* Listen to the candidate as they're being interviewed
+ * Work out when they're stuck (but give them enough time to come up with an answer - count slowly in your head to 10 before intervening)
+ * If they're not telling you what they're thinking, encourage them to talk aloud - say something like "Talk through what you're thinking"
+ * Give nudges (ideally by asking questions), not answers, to help them get unstuck
+* Understand their code, and be able to work out whether it works
+* Identify edge cases their code does not work for
+
+## Giving feedback
+
+After you interview someone, you will give them feedback. Think about what feedback you would appreciate. Some examples of topics:
+* How clearly did they communicate their ideas? (Think about feedback you've heard in demos before)
+* Did you always know what they were thinking/doing?
+* How easy was their code to read and understand?
+* How open were they to help?
+* Did they come across as a person you'd want to work with?
+* How well do you think they solved the problem? (Note: This doesn't mean "did they solve it the same way you would", though that can be an interesting comparison).
+
+## Doing the interview (30 minutes per interview)
+
+In pairs, take turns interviewing your partner. In each interview, one of you will be the interviewer and the other the candidate.
+
+You should:
+* Candidate: Open VS Code on your laptop.
+* Interviewer: Spend {{}}2{{}} introducing the problem. It's ok to leave some details out (hopefully the candidate will ask about them), but the question should make sense.
+* Candidate: Spend {{}}20{{}} solving the problem. This should be an interactive dialogue, where the interviewer and candidate are talking throughout.
+* Spend {{}}8{{}} giving feedback and discussing the interview and experience.
+
+Then swap.
+
+## Discussion (30 minutes)
+
+As a whole class, discuss your experience. What went well? What did/didn't you understand? What things felt uncomfortable? What could you have done differently? Do not focus on the technical specifics of the interview question you did. Focus on general things that will help you in your next interview.
diff --git a/terminal-skills/README.md b/terminal-skills/README.md
index 53ed6ed5..75fe0dd7 100644
--- a/terminal-skills/README.md
+++ b/terminal-skills/README.md
@@ -37,7 +37,7 @@ Developers often write tools that other people can use in scripts or pipelines.
For instance, `git` exposes a lot of information that you can conveniently consume in a script.
-We can find the email addresses of people who have contributed to a Git repo by running:
+We can find the names of people (or bots) who have contributed to a Git repo by running:
`git log | grep '^Author:' | awk -F'[<>]' '{print $2}' | grep -v 'users\.noreply\.github\.com' | sort | uniq`
diff --git a/user-needs-and-acceptance-criteria/README.md b/user-needs-and-acceptance-criteria/README.md
new file mode 100644
index 00000000..f098de2c
--- /dev/null
+++ b/user-needs-and-acceptance-criteria/README.md
@@ -0,0 +1,133 @@
+# User Needs and Acceptance Criteria
+
+## Learning objectives
+
+```objectives
+- [ ] Identify user personas.
+- [ ] Define user needs for different user personas.
+- [ ] Identify the benefits of using Who/What/Why in user stories.
+- [ ] Write acceptance criteria in Given/When/Then format.
+- [ ] Identify the benefits of using Given/When/Then in acceptance criteria.
+```
+
+## Introduction
+
+When designing and building systems, understanding the customer is critically important. If we don't understand the customer, we may build something that solves the wrong problem, or something that the user can't use.
+
+In this workshop, we are going to think about designing a digital system for a pub. We will think about different user personas, their needs, and how we may be able to solve them.
+
+## Identify User Types (5 minutes)
+
+Get in small groups or pairs to brainstorm and list at least 3 different users of a pub system.
+
+
+
+Expand for some possible users - compare your list to these when you're done
+
+* Pub Customer (guest)
+* Bartender/Waitstaff
+* Pub Manager/Owner
+* Kitchen Staff
+* Supplier/Delivery Person
+
+
+
+## Define User Needs (10 minutes)
+
+For each user type, take 10 mins to discuss and write down their main needs or goals when interacting with the pub's system.
+
+
+
+Expand for volunteer facilitation hints
+
+Examples:
+
+| User Type | Needs / Goals |
+| ------------- | --------------------------------------------------------------- |
+| Customer | Browse menu, place order, reserve table, pay bill, leave review |
+| Bartender | View orders, update order status, manage reservations |
+| Manager/Owner | View sales reports, manage menu, oversee staff schedules |
+| Kitchen Staff | Receive new orders, update order status |
+| Supplier | Schedule deliveries, update inventory |
+
+
+
+## Write User Stories (10 minutes)
+
+Select at least one user type within your groups and write a user story for them, focusing on a specific need.
+
+
+
+Expand for volunteer facilitation hints
+
+Format could be as follows:
+
+* "As a _user type_, I want to _do something_, so that _benefit_."
+
+Example could be as follows:
+
+* "As a customer, I want to reserve a table online, so that I can ensure seating when I arrive."
+
+
+
+## Acceptance Criteria with Gherkin (15 minutes)
+
+For each user story, write acceptance criteria using [Gherkin syntax](https://cucumber.io/docs/gherkin/reference/).
+
+
+
+Expand for volunteer facilitation hints
+
+Make sure Gherkin syntax is clear for trainees as below:
+
+```
+Given [context]
+When [action]
+Then [expected outcome]
+```
+
+Ask trainees to think of examples if theyβre stuck. See below for examples:
+
+* Customer Table Reservation:
+
+```
+Given I am a registered customer on the pub's website
+When I select a date and time and submit a reservation request
+Then I should see a confirmation message with my reservation details
+```
+
+* Bartender Viewing Orders:
+
+```
+Given I am logged in as a bartender
+When a new order is placed by a customer
+Then I should see the new order appear at the top of my orders list
+```
+
+
+
+## Group Sharing & Discussion (10 minutes)
+
+Take {{}}5{{}} to present your user stories and acceptance criteria.
+
+Discuss what makes acceptance criteria clear and testable for {{}}5{{}}.
+
+
+
+Expand for volunteer facilitation hints
+
+Make sure the trainees receive peer feedback and volunteer guidance.
+
+
+
+## Wrap-Up (5 minutes)
+
+As a group, summarise the key takeaways and discuss why applying these practices in future projects could be useful.
+
+
+
+Expand for volunteer facilitation hints
+
+Make sure we've covered user-centric thinking, specificity in requirements, clarity in acceptance criteria.
+
+