Skip to content

Latest commit

Β 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎭 Jokester

Find your perfect joke. No bad days allowed.

Live Demo GitHub Repo Node.js Express Deployed on Vercel


A full-stack web application that lets users customise and discover jokes by category, format, and content filters β€” powered by the free JokeAPI v2. Built as a capstone project for the Complete Web Development Bootcamp by Angela Yu.


Jokester Banner

image

πŸ“– Table of Contents


✨ Features

Feature Description
🎲 7 Joke Categories Any, Programming, Miscellaneous, Dark, Pun, Spooky, Christmas
πŸ“ Joke Formats One-liners or interactive Setup & Punchline
πŸ₯ Tap-to-Reveal Two-part jokes hide the punchline until the user is ready
πŸ›‘οΈ Content Filters Blacklist unwanted themes: NSFW, Religious, Political, Racist, Sexist, Explicit
πŸ˜… Graceful Errors Friendly messages when the API is down or no jokes match
πŸ“± Fully Responsive Works beautifully on mobile, tablet, and desktop
⚑ Zero Auth Required No API keys needed β€” works out of the box
🌍 Live on Vercel Deployed and accessible anywhere in the world

πŸ”΄ Live Demo

🌐 https://jokester-omega.vercel.app/

Open the link, pick your filters, hit the button β€” and get a joke instantly.


πŸ› οΈ Tech Stack

Frontend        β†’ HTML5 Β· CSS3 Β· Vanilla JavaScript Β· EJS Templating
Backend         β†’ Node.js Β· Express.js
HTTP Client     β†’ Axios
API             β†’ JokeAPI v2 (free, no auth, CORS-enabled)
Fonts           β†’ Google Fonts (Fraunces + Nunito)
Hosting         β†’ Vercel

Why these choices?

  • Express.js β€” minimal, fast server framework ideal for routing and middleware
  • Axios β€” cleaner API than fetch for server-side HTTP requests, with built-in error handling
  • EJS β€” simple templating that lets the server inject dynamic data directly into HTML
  • JokeAPI β€” free, no API key needed, CORS-enabled, and returns structured JSON with rich filtering options

πŸ“ Project Structure

jokester/
β”‚
β”œβ”€β”€ index.js                  ← Express server (routes, Axios calls, error handling)
β”‚
β”œβ”€β”€ views/
β”‚   └── index.ejs             ← Main EJS template (all dynamic rendering)
β”‚
β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ css/
β”‚   β”‚   └── style.css         ← All styles (neo-brutalist design system)
β”‚   └── js/
β”‚       └── app.js            ← Client-side JS (punchline reveal, pill sync)
β”‚
β”œβ”€β”€ package.json              ← Dependencies and npm scripts
β”œβ”€β”€ vercel.json               ← Vercel deployment configuration
└── README.md                 ← You are here

βš™οΈ How It Works ?

User fills form  β†’  POST /joke  β†’  Express builds API URL  β†’  Axios calls JokeAPI
                                                                      ↓
Browser renders  ←  EJS renders  ←  Express passes joke data  ←  Response received

Step-by-step flow

  1. User visits GET / β€” the home page renders with an empty state and the filter form.
  2. User configures their joke preferences (category, format, blacklist flags) and submits.
  3. Express receives the POST /joke request and reads req.body.
  4. The server constructs a dynamic JokeAPI URL:
    https://v2.jokeapi.dev/joke/{category}?blacklistFlags={flags}&type={type}
    
  5. Axios sends the GET request to JokeAPI and awaits the response.
  6. The data is passed into the EJS template, which renders the joke differently based on type (single vs twopart).
  7. For two-part jokes, a JavaScript button hides the punchline until the user taps to reveal it.

πŸš€ Getting Started

Prerequisites

Make sure you have the following installed:

  • Node.js v18 or higher
  • npm (comes with Node.js)

1. Clone the repository

git clone https://github.com/razazaheer12/Jokester.git
cd Jokester

2. Install dependencies

npm install

3. Run the development server

# With auto-reload (recommended)
npx nodemon index.js

# Or run once without nodemon
node index.js

4. Open in browser

http://localhost:3000

That's it β€” no .env file, no API keys, no additional setup required.


🌐 API Reference

This project uses JokeAPI v2 β€” completely free, no authentication required.

Base URL

https://v2.jokeapi.dev/joke/{category}

Parameters used

Parameter Type Example Description
category path Programming Joke category (or Any)
type query twopart single or twopart
blacklistFlags query nsfw,explicit Comma-separated content flags to exclude

Example request

GET https://v2.jokeapi.dev/joke/Programming?blacklistFlags=nsfw,explicit&type=twopart

Example response (two-part)

{
  "error": false,
  "category": "Programming",
  "type": "twopart",
  "setup": "Why did the programmer quit his job?",
  "delivery": "Because he didn't get arrays.",
  "flags": {
    "nsfw": false,
    "religious": false,
    "political": false,
    "racist": false,
    "sexist": false,
    "explicit": false
  },
  "id": 210,
  "safe": true,
  "lang": "en"
}

Available categories

Any Β· Programming Β· Misc Β· Dark Β· Pun Β· Spooky Β· Christmas

Available blacklist flags

nsfw Β· religious Β· political Β· racist Β· sexist Β· explicit


🎨 Design Highlights

The UI uses a neo-brutalist design language with a bright, playful twist:

  • Typography β€” Fraunces (serif, italic) for jokes; Nunito (rounded sans-serif) for UI
  • Color palette β€” Sunshine yellow #FFE14D, coral #FF6B6B, mint #4ECDC4, and navy #1A1A2E
  • Cards β€” thick 2.5px borders + hard 6px offset box shadows for that chunky, tactile feel
  • Animated blobs β€” blurred color blobs float in the background using CSS @keyframes
  • Interactive pills β€” category and filter buttons toggle with smooth hover + active states
  • Reveal animation β€” the joke card pops in with a spring cubic-bezier animation on each new result
  • Mobile-first β€” layout adapts gracefully from 320px screens upward

πŸ”’ Error Handling

Errors are handled at two levels:

Server-side (in index.js)

try {
  const response = await axios.get(url);
  const data = response.data;

  if (data.error) {
    // JokeAPI returned no results for these filters
    return res.render("index", { joke: null, error: "No jokes found...", query: req.body });
  }

  res.render("index", { joke: data, error: null, query: req.body });

} catch (err) {
  // Network failure or API down
  console.error("JokeAPI error:", err.message);
  res.render("index", { joke: null, error: "Couldn't reach the Joke API right now.", query: req.body });
}

Client-side (in index.ejs)

<% if (error) { %>
  <div class="alert alert-error">
    <span class="alert-icon">πŸ˜…</span>
    <p><%= error %></p>
  </div>
<% } %>

The form also preserves user selections after an error, so they don't have to re-configure their filters.


πŸ“¦ Deployment

This project is deployed on Vercel with a custom vercel.json configuration to support the Express server.

vercel.json

{
  "version": 2,
  "builds": [{ "src": "index.js", "use": "@vercel/node" }],
  "routes": [{ "src": "/(.*)", "dest": "index.js" }]
}

Deploy your own copy

# Install Vercel CLI
npm install -g vercel

# Deploy from your project root
vercel

# Follow the prompts β€” your site will be live in seconds

πŸ“š Learning Objectives

This project was built to demonstrate:

Skill Implementation
Express routing GET / and POST /joke endpoints in index.js
Axios HTTP client Server-side API calls with async/await and try/catch
EJS templating Dynamic rendering of joke data, error states, and form state preservation
API integration Consuming a public REST API with query parameter construction
Error handling Both API-level (data.error) and network-level (catch) errors handled gracefully
Static file serving express.static("public") for CSS and JS
Form handling express.urlencoded middleware + req.body parsing
Deployment Vercel serverless deployment with vercel.json config
Code organisation Structured directory layout with separation of concerns

πŸ™Œ Credits

Resource Link
Course The Complete Web Development Bootcamp – Angela Yu
API JokeAPI v2 by sv443
Fonts Google Fonts – Fraunces & Nunito
Hosting Vercel

Made with πŸ˜‚ and β˜• by razazaheer12

If this project made you laugh even once β€” it did its job.

⭐ Star the repo if you enjoyed it!

About

A bright, playful joke-finder built with Express, EJS, and Axios, powered by the free JokeAPI. Users can pick a joke category, format (one-liner vs setup/punchline), and block any themes, they don't want then get an instant joke.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages