Weekly Code Quickies

Weekly Code Quickies

By Wealth DomeNewsTech News
Download on the App Store

Weekly Code Quickies episodes

  • Build a Live Stock Price Tracker with React, Tailwind CSS & Alpha Vantage API

    Looking to build your own real-time stock market tracker app? In this hands-on tutorial, we’ll use React, Tailwind CSS, and the Alpha Vantage API to create a sleek and functional live stock price tracker.

    Whether you’re a frontend dev or a beginner trying to get into finance tech, this is a project-based learning opportunity that teaches practical skills while building something useful.

    In this project, you'll learn how to:

    - Fetch live stock prices from an API using React hooks

    - Manage dynamic lists and user input

    - Display loading states and error handling

    - Style your app with Tailwind CSS for a professional look

    Perfect for beginners and intermediate developers looking to boost their React skills!

    🛠️ What We'll Build

    * 🔍 A stock search bar with live suggestions

    * 💰 A dashboard showing real-time prices

    * 📉 Dynamic price color change (green/red)

    * 📱 Clean Tailwind-powered responsive UI

    * 🌐 API integration with Alpha Vantage (free key!)

    🚀 Technologies Used

    * React + Vite

    * Tailwind CSS

    * Alpha Vantage API (Get your key)

    * React hooks: useState, useEffect, fetch

    🧱 Project Setup

    bash

    CopyEdit

    npm create vite@latest stock-tracker --template react cd stock-tracker npm install npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p

    Tailwind Setup (tailwind.config.js):

    js

    CopyEdit

    content: [ "./index.html", "./src/**/*.{js,ts,jsx,tsx}", ],

    Tailwind in index.css:

    css

    CopyEdit

    @tailwind base; @tailwind components; @tailwind utilities;

    🔗 API Setup with Alpha Vantage

    Sign up at AlphaVantage.co and grab your API key.

    Example fetch call:

    js

    CopyEdit

    const fetchStockPrice = async (symbol) => { const res = await fetch(`https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=YOUR_KEY`); const data = await res.json(); return data['Global Quote']; };

    📊 Displaying Stock Data

    Example JSX:

    jsx

    CopyEdit

    {stockName}

    0 ? 'text-green-500' : 'text-red-500'}`}> ${stockPrice} ({priceChange}%)

    🎨 UI Tips with Tailwind CSS

    * Use grid-cols-2 or flex justify-between for layouts

    * Add a search input with a dropdown using absolute, bg-white, z-10

    * Animate loading state with animate-pulse

    📱 Optional Enhancements

    * Save recent stock symbols to localStorage

    * Add a chart using Chart.js or Recharts

    * Show currency, volume, or market cap

    Source Code:

    import React, { useState, useEffect } from "react";

    // StockPrice component fetches and displays the price for a given ticker
    function StockPrice({ ticker = "" }) {
    const [price, setPrice] = useState(null); // Holds the fetched price
    const [loading, setLoading] = useState(true); // Loading state
    const [error, setError] = useState(null); // Error state
    useEffect(() => {
    // Fetch stock price from Alpha Vantage API
    const fetchStockPrice = async () => {
    try {
    setLoading(true);
    const apiKey = import.meta.env.VITE_ALPHAVANTAGE_API_KEY; // Uncomment and set your API key
    const response = await fetch(
    `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${ticker}&apikey=${apiKey}`
    );
    if (!response.ok)
    throw new Error(`HTTP error! status: ${response.status}`);
    const data = await response.json();
    // Check if the API returned a valid price
    if (data["Global Quote"] && data["Global Quote"]["05. price"]) {
    setPrice(parseFloat(data["Global Quote"]["05. price"]).toFixed(2));
    setError(null);
    } else {
    setError("Could not retrieve price for this ticker.");
    setPrice(null);
    }
    } catch (e) {
    setError(`Error fetching data: ${e.message}`);
    setPrice(null);
    } finally {
    setLoading(false);
    }
    };
    fetchStockPrice(); // Call the fetch function when ticker changes
    }, [ticker]);
    return (

    {/* Display the ticker symbol */}
    {ticker}
    {/* Show loading spinner while fetching */}
    {loading && (

    Loading price...

    )}
    {/* Show error message if there is an error */}
    {error &&

    {error}

    }
    {/* Show the price if loaded successfully */}
    {!loading && !error && price !== null && (

    ${price}

    )}
    {/* Show message if no data is available */}
    {!loading && !error && price === null && (

    No data available.

    )}
    );
    }
    // Main StockPriceTracker component manages the list of tickers and input
    export default function StockPriceTracker() {
    const [tickers, setTickers] = useState(["NVDA", "MSFT", "GOOGL"]); // Initial tickers
    const [input, setInput] = useState(""); // Input for new ticker
    // Add a new ticker to the list
    const addTicker = () => {
    const val = input.trim().toUpperCase();
    if (val && !tickers.includes(val)) {
    setTickers([...tickers, val]);
    setInput("");
    }
    };
    return (
    {/* App title */}
    My Stock Tracker
    {/* Input and Add button for new tickers */}
    setInput(e.target.value)}
    placeholder="Add ticker (e.g. AAPL)"
    />
    Add
    {/* Display StockPrice components for each ticker */}
    {tickers.map((ticker) => (
    ))}
    );
    }



    Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
    31 min
  • Mastering React Router v7 with TailwindCSS & Vite – Complete Crash Course

    In this guide, we’ll walk step-by-step through creating a fully functional React app using React Router v7, styled with TailwindCSS, and powered by Vite. This is your go-to tutorial for learning client-side routing in React — from setup to nested routes and 404 pages.

    📦 Technologies Used

    * React 19 (via Vite)

    * React Router v7.6.3

    * TailwindCSS 4.1+

    * Vite (for fast build + dev server)

    🛠️ Project Setup with Vite & TailwindCSS

    React Router Crash Course: Step-by-Step Guide

    React Router is the standard routing library for React. In this crash course, we’ll build a simple multi-page app using React Router v6+ and Vite. Let’s get started!

    1. Project Setup

    First, create a new React project using Vite:

    npm create vite@latest react-router-crash-course -- --template react

    cd react-router-crash-course
    npm install

    Install React Router:

    npm install react-router-dom

    2. Project Structure

    Organize your files as follows:

    src/

    App.jsx
    main.jsx
    components/
    Button.jsx
    Navigation.jsx
    pages/
    HomePage.jsx
    AboutPage.jsx
    ContactPage.jsx
    ProductsPage.jsx
    ProductDetailPage.jsx
    NotFoundPage.jsx
    Dashboard/
    DashboardLayout.jsx
    DashboardHome.jsx
    DashboardProfile.jsx
    DashboardSettings.jsx

    3. Setting Up the Router

    In main.jsx, wrap your app with BrowserRouter:

    import React from "react";

    import ReactDOM from "react-dom/client";
    import { BrowserRouter } from "react-router-dom";
    import App from "./App.jsx";
    import "./App.css";
    ReactDOM.createRoot(document.getElementById("root")).render(
    );

    4. Defining Routes

    In App.jsx, set up your routes:

    import { Routes, Route } from "react-router-dom";

    import Navigation from "./components/Navigation";
    import HomePage from "./pages/HomePage";
    import AboutPage from "./pages/AboutPage";
    import ContactPage from "./pages/ContactPage";
    import ProductsPage from "./pages/ProductsPage";
    import ProductDetailPage from "./pages/ProductDetailPage";
    import NotFoundPage from "./pages/NotFoundPage";
    import DashboardLayout from "./pages/Dashboard/DashboardLayout";
    import DashboardHome from "./pages/Dashboard/DashboardHome";
    import DashboardProfile from "./pages/Dashboard/DashboardProfile";
    import DashboardSettings from "./pages/Dashboard/DashboardSettings";
    function App() {
    return (
    <>
    } />
    } />
    } />
    } />
    } />
    }>
    } />
    } />
    } />
    } />
    );
    }
    export default App;

    5. Creating Navigation

    In components/Navigation.jsx, add navigation links:

    import { NavLink } from "react-router-dom";

    function Navigation() {
    return (

    Home
    About
    Contact
    Products
    Dashboard
    );
    }
    export default Navigation;

    6. Building Pages

    Create simple components for each page in the pages/ directory. Example for HomePage.jsx:

    function HomePage() {

    return

    Welcome to the Home Page!;
    }
    export default HomePage;

    Repeat for AboutPage.jsx, ContactPage.jsx, etc.

    7. Dynamic Routes

    In ProductDetailPage.jsx, use the useParams hook to get the product ID:

    import { useParams } from "react-router-dom";

    function ProductDetailPage() {
    const { id } = useParams();
    return

    Product Details for ID: {id};
    }
    export default ProductDetailPage;

    8. Nested Routes (Dashboard Example)

    In DashboardLayout.jsx, use the Outlet component:

    import { Outlet, NavLink } from "react-router-dom";

    function DashboardLayout() {
    return (

    Dashboard
    Home
    Profile
    Settings
    );
    }
    export default DashboardLayout;

    9. Handling 404s

    In NotFoundPage.jsx:

    function NotFoundPage() {

    return

    404 - Page Not Found;
    }
    export default NotFoundPage;

    10. Running the App

    Start your development server:

    npm run dev

    Visit

    http://localhost:5173

    to see your app in action!

    Conclusion

    You now have a working React app with multiple pages, nested routes, dynamic routes, and a 404 page—all powered by React Router. Experiment by adding more pages or features!



    Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
    54 min
  • 🧠 React Components Deep Dive: Props, State, Composition & Hooks (2025)

    In this tutorial, you'll get a complete understanding of React components including how to build and structure them using best practices. You'll learn about functional components, props, state, JSX, hooks, composition, and how to break an app into reusable modules.

    📽️ YouTube Video Title (High CTR)

    🔧 Step-by-Step Tutorial

    1. 📦 What is a Component in React?

    * A component is a reusable and self-contained part of the UI.

    * It’s either a function or class (function preferred).

    * Allows splitting the UI into isolated pieces.

    function MyComponent() {

    return

    Hello World;
    }

    2. 🧩 Types of Components

    ✅ Functional Components (modern, preferred)

    const Welcome = () =>

    Welcome!;

    ❌ Class Components (legacy)

    class Welcome extends React.Component {

    render() {
    return

    Welcome!;
    }
    }

    3. 🛠 Using Props

    Props = "properties" → input data passed to a component.They are read-only and passed via JSX attributes.

    function Greeting({ name }) {

    return

    Hello, {name}!

    ;
    }

    4. 🔁 State Management

    State = data that can change.Use useState to manage it in a functional component.

    const [count, setCount] = useState(0);

    Updating state triggers a re-render of the component.

    5. ⏱ Lifecycle with useEffect

    React uses useEffect() for side effects like fetching data.

    useEffect(() => {

    console.log("Component Mounted");
    }, []); // Empty array = run once

    6. 💻 JSX Syntax

    JSX = HTML + JavaScript hybrid syntax.It compiles to React.createElement() behind the scenes.

    const App = () => (

    Hello JSX!
    );

    7. 🧱 Component Composition

    Components can include other components → reusable UIs.

    const Page = () => (

    );

    8. 📦 Exporting and Importing Components

    Create a component:

    const Footer = () =>

    © 2025;
    export default Footer;

    Use it:

    import Footer from './components/Footer';

    9. 📁 Project Refactor Example

    We extracted Footer.jsx, Home.jsx, Page.jsx, RecipePage.jsx, RecipeCard.jsx, and RecipeModal.jsx components into a structured folder system.

    Folder Structure:

    src/

    ├── components/
    │ ├── Footer.jsx
    │ ├── Page.jsx
    ├── pages/
    │ ├── Home.jsx
    │ ├── RecipePage.jsx
    │ ├── Recipes/
    │ │ ├── RecipeCard.jsx
    │ │ ├── RecipeModal.jsx

    10. 📚 Best Practices

    * ✅ Name components with capital letters

    * ✅ One export default per file

    * ✅ Keep components small & focused

    * ✅ Use props to customize components

    * ✅ Return a single parent element



    Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
    24 min
  • 🔍 Implement Search & Category Filtering in React with TailwindCSS (2025 Guide)

    🔍 Implement Search & Category Filtering in React with TailwindCSS (2025 Guide)

    In this guide, you’ll learn how to implement powerful search and category filtering in a React application using TailwindCSS for styling. This builds on a previous project where we created a responsive recipe website.

    By the end of this tutorial, you'll be able to:

    * Filter recipe cards by text input

    * Filter by category dropdown

    * Clear search with a single click

    * Ensure case-insensitive matching

    ✅ Prerequisites

    * A React app already set up (ideally with TailwindCSS + recipe data)

    * Basic understanding of React state and hooks

    🧱 Step 1: Create State for Search and Category

    Inside your RecipesPage.jsx (or App.jsx if everything is in one file):

    const [searchQuery, setSearchQuery] = useState("");

    const [category, setCategory] = useState("");
    const [filteredRecipes, setFilteredRecipes] = useState(recipes);

    🎨 Step 2: Create the UI

    🔍 Search + Filter Inputs

    Featured Recipes
    setSearchQuery(e.target.value)}
    className="w-full md:w-1/2 px-4 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-amber-500"
    />
    setCategory(e.target.value)}
    className="w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-amber-500"
    >
    All Categories
    {[...new Set(recipes.map(recipe => recipe.category))].map((cat, i) => (
    {cat}
    ))}
    {
    setSearchQuery("");
    setCategory("");
    }}
    className="cursor-pointer bg-gradient-to-r from-amber-500 to-orange-500 hover:from-orange-500 hover:to-amber-500 text-white px-6 py-2 rounded transition duration-300"
    >
    Clear Search

    ⚙️ Step 3: Search Logic with useEffect

    useEffect(() => {

    const query = searchQuery.toLowerCase();
    const result = recipes.filter(recipe =>
    recipe.title.toLowerCase().includes(query) ||
    recipe.ingredients.some(ing => ing.toLowerCase().includes(query)) ||
    recipe.category.toLowerCase().includes(query)
    );
    if (category) {
    setFilteredRecipes(result.filter(recipe => recipe.category === category));
    } else {
    setFilteredRecipes(result);
    }
    }, [searchQuery, category]);

    This runs every time the search query or category changes.

    📦 Step 4: Display Filtered Recipes

    {filteredRecipes.length > 0 ? (
    filteredRecipes.map((recipe, i) => (
    ))
    ) : (

    No recipes found.

    )}

    🧠 Bonus: Tips

    * Use toLowerCase() to make searching case-insensitive

    * Use Set to generate unique categories

    * Add debounce if your search data is large

    * For UX, make the clear button instantly reset filters

    📈 SEO Keywords

    * React search filter tutorial 2025

    * Tailwind CSS form input search

    * Recipe search filter React example

    * Case-insensitive search with useEffect

    * Responsive dropdown in React + TailwindCSS



    Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
    23 min
  • React Crash Course 2025 – Build Your First App with Hooks, Components & State!

    📝 Description

    Ready to learn React in 2025? This crash course walks you through creating your first real-world React app with hooks, components, and JSX.

    ✅ What you'll learn:

    * Setting up React with Create React App

    * JSX, Props, State & Hooks

    * Styling, Conditional Rendering, Lists

    * Component architecture & folder structure

    #ReactJS #CrashCourse #WebDevelopment #JavaScript #FrontendDev #ReactHooks #React2025

    🚀 React.js Crash Course 2025 – Build Your First App from Scratch

    Welcome to this beginner-friendly React.js crash course for 2025! Whether you're transitioning from HTML, CSS, and JavaScript or starting fresh, this tutorial will give you a rock-solid foundation in React with best practices, clean structure, and modern JavaScript techniques.

    📦 Step 1: What Is React.js?

    React is a JavaScript library for building user interfaces, created and maintained by Meta (Facebook). It allows you to create reusable components, use a virtual DOM for faster rendering, and structure your frontend with clean, component-based architecture.

    React is not a full-blown framework like Angular—think of it as the view layer of your app. It’s great for building single-page applications (SPAs).

    🧱 Step 2: Setting Up React

    ✅ Prerequisites:

    * Node.js & npm (Install from nodejs.org)

    * A code editor like VS Code

    🛠 Create a New React App

    npx create-react-app my-app

    Replace my-app with your project name.

    Navigate into your app:

    cd my-app

    Start the app:

    npm start

    Your React app will open at

    http://localhost:3000

    📂 Step 3: Project Structure Overview

    React generates this structure:

    my-app/

    ├── node_modules/
    ├── public/
    │ └── index.html
    ├── src/
    │ ├── App.js
    │ ├── App.css
    │ ├── index.js
    │ └── components/ (your custom folder)
    ├── package.json

    * App.js: Main component

    * App.css: Main stylesheet

    * index.js: App entry point

    🧩 Step 4: Understanding JSX & Components

    Create a Functional Component

    // src/components/Welcome.jsx

    function Welcome({ message = "World" }) {
    return

    Hello {message}!;
    }
    export default Welcome;

    Import & Use It

    // App.js

    import Welcome from './components/Welcome';
    function App() {
    return (

    );
    }

    JSX Notes

    * Always return a single root element (use <>... if needed).

    * Use className instead of class.

    ⚛️ Step 5: Using State with useState

    import { useState } from 'react';

    function App() {
    const [count, setCount] = useState(0);
    return (

    Count: {count}

    setCount(count + 1)}>Increment
    );
    }

    ⏱ Step 6: Using Effects with useEffect

    import { useEffect, useState } from 'react';

    function App() {
    const [seconds, setSeconds] = useState(0);
    useEffect(() => {
    const interval = setInterval(() => {
    setSeconds(s => s + 1);
    }, 1000);
    return () => clearInterval(interval); // Cleanup
    }, []);
    return

    Time passed: {seconds}s

    ;
    }

    🎨 Step 7: Styling in React

    Option 1: CSS File

    /* App.css */

    .App {
    background-color: aqua;
    height: 100vh;
    }

    Option 2: Inline Style

    const myStyle = {

    backgroundColor: 'black',
    color: 'white',
    fontSize: '2rem'
    };
    return

    Styled Heading;

    🔁 Step 8: Conditional Rendering

    const [isLoggedIn, setIsLoggedIn] = useState(false);

    return (

    {isLoggedIn ? : }
    setIsLoggedIn(!isLoggedIn)}>Toggle Login
    );

    Or with &&:

    {hasAccess && }

    🧾 Step 9: Lists and Keys

    const items = ["A", "B", "C"];

    return (

      {items.map((item, index) => (
    • {item}
    • ))}
      );

      ⚠️ Use unique IDs for production (not index as key).

      🗂 Step 10: Folder Structure Best Practices

      src/

      ├── components/
      │ ├── Header.jsx
      │ ├── Button.jsx
      ├── pages/
      │ ├── Home.jsx
      │ ├── About.jsx
      ├── hooks/
      │ └── useToggle.js
      ├── App.js
      ├── index.js

      Clean up unused files like logo.svg, App.test.js, etc.

      🚀 Next Steps

      * Use React Router for navigation

      * Deploy using Vercel or Netlify

      * Add form handling and API calls

      Stay tuned for the next part where we build a real React project from scratch!

      Download the PDF file here:



      Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
      37 min
    • 🧑‍🍳 Build a Dynamic Recipe Website with Tailwind CSS & JavaScript (No Frameworks)

      🚀 Live Features:

      * Sticky navigation

      * Responsive hero section with call to action

      * Dynamically generated recipe cards

      * Recipe search by keyword, category, or ingredient

      * Modal popups with recipe details

      * Contact form with Font Awesome icons

      * Auto-updating copyright

      🧱 Step 1: Project Setup

      Create the folder structure:

      📁 dynamic-recipe-site/

      ├── index.html
      ├── style.css (optional)
      ├── script.js

      🌐 Step 2: Build the Layout (HTML + Tailwind)

      🧭 Sticky Navbar

      Tasty Recipes
      • Home
      • Recipes
      • About
      • Contact

        🏠 Hero Section

        Welcome to Tasty Recipes

        Discover a world of delicious recipes and culinary inspiration.

        Explore Recipes

        🍝Featured Recipes Section

        Featured Recipes
        Search Recipes
        Search

        📜 Step 3: About & Contact Sections

        🙋 About Us

        About Us

        Welcome to Tasty Recipes, your go-to source for delicious and
        inspiring recipes from around the world.

        Our mission is to provide you with high-quality, easy-to-follow
        recipes that will help you create memorable meals.

        📞 Contact Form

        Contact Us

        Have a question or suggestion? We'd love to hear from you!

        Email us at: [email protected]

        Send Message

        🔚 Footer

        © 2025 Tasty Recipes. All rights reserved.

        ⚙️ Step 5: Load Recipes Dynamically with JavaScript

        const recipes = [

        {
        title: "Spaghetti Carbonara",
        category: "Pasta",
        image: "https://www.themealdb.com/images/media/meals/wvqpwt1468339226.jpg",
        ingredients: [
        "200g spaghetti",
        "100g pancetta",
        "2 large eggs",
        "50g Pecorino Romano cheese",
        "Black pepper",
        "Salt",
        ],
        instructions: [
        "Cook the spaghetti in salted boiling water until al dente.",
        "While the pasta is cooking, cut the pancetta into small cubes and fry until crispy.",
        "In a bowl, whisk together the eggs, cheese, and a generous amount of black pepper.",
        "Drain the spaghetti and add it to the pancetta pan. Mix well.",
        "Remove the pan from the heat and add the egg mixture, stirring quickly to create a creamy sauce.",
        "Serve immediately with extra cheese and pepper.",
        ],
        },
        {
        title: "Classic Margherita Pizza",
        category: "Pizza",
        image: "https://www.themealdb.com/images/media/meals/x0lk931587671540.jpg",
        ingredients: [
        "250g strong bread flour",
        "1 tsp dried yeast",
        "1 tsp sugar",
        "1 tsp salt",
        "150ml warm water",
        "2 tbsp olive oil",
        "100g tomato sauce",
        "150g mozzarella cheese",
        "Fresh basil leaves",
        ],
        instructions: [
        "In a large bowl, combine flour, yeast, sugar, and salt.",
        "Add warm water and olive oil, and mix to form a dough.",
        "Knead the dough for about 10 minutes until smooth.",
        "Let the dough rise in a warm place for 1 hour.",
        "Preheat oven to 220°C (425°F).",
        "Roll out the dough on a floured surface.",
        "Spread tomato sauce over the base, add mozzarella cheese, and bake for 15-20 minutes.",
        "Garnish with fresh basil leaves before serving.",
        ],
        },
        {
        title: "Chocolate Brownies",
        category: "Dessert",
        image: "https://www.themealdb.com/images/media/meals/yypvst1511386427.jpg",
        ingredients: [
        "150g unsalted butter",
        "200g dark chocolate",
        "150g sugar",
        "2 large eggs",
        "100g all-purpose flour",
        "30g cocoa powder",
        "1 tsp vanilla extract",
        "Pinch of salt",
        ],
        instructions: [
        "Preheat oven to 180°C (350°F). Grease and line a square baking tin.",
        "Melt butter and chocolate together over low heat.",
        "In a bowl, whisk together sugar and eggs until light and fluffy.",
        "Stir in the melted chocolate mixture and vanilla extract.",
        "In a separate bowl, whisk together flour, cocoa powder, and salt.",
        "Gently fold the dry ingredients into the wet ingredients until just combined.",
        "Pour the batter into the prepared tin and bake for 20-25 minutes.",
        "Let it cool completely before cutting into squares.",
        ],
        },
        {
        title: "Fresh Garden Salad",
        category: "Salad",
        image: "https://www.themealdb.com/images/media/meals/urtwux1486983078.jpg",
        ingredients: [
        "6 cups mixed salad greens",
        "2 medium tomatoes, diced",
        "1 cucumber, sliced",
        "1 red onion, thinly sliced",
        "1 bell pepper, chopped",
        "1/2 cup olive oil",
        "3 tbsp balsamic vinegar",
        "1 tsp Dijon mustard",
        "1 clove garlic, minced",
        "Salt and pepper to taste",
        ],
        instructions: [
        "Wash and dry all vegetables thoroughly.",
        "In a large bowl, combine the salad greens, tomatoes, cucumber, red onion, and bell pepper.",
        "In a small bowl, whisk together olive oil, balsamic vinegar, Dijon mustard, minced garlic, salt, and pepper.",
        "Drizzle the dressing over the salad and toss gently to combine.",
        "Serve immediately.",
        ],
        },
        {
        title: "Grilled Salmon with Lemon Herbs",
        category: "Main Course",
        image: "https://www.themealdb.com/images/media/meals/1548772327.jpg",
        ingredients: [
        "4 salmon fillets",
        "2 tbsp olive oil",
        "2 cloves garlic, minced",
        "1 lemon, sliced",
        "2 tbsp fresh dill, chopped",
        "2 tbsp fresh parsley, chopped",
        "Salt and pepper to taste",
        ],
        instructions: [
        "Preheat grill to medium-high heat.",
        "In a small bowl, mix olive oil, minced garlic, dill, and parsley.",
        "Place salmon fillets on a large piece of aluminum foil. Season with salt and pepper.",
        "Spread the herb mixture over the salmon fillets and top with lemon slices.",
        "Fold the foil to create a sealed packet. Grill for 12-15 minutes, or until salmon is cooked through.",
        "Serve hot with your favorite sides.",
        ],
        },
        {
        title: "Vegetable Stir-Fry",
        category: "Stir-Fry",
        image: "https://www.themealdb.com/images/media/meals/wuxrtu1483564410.jpg",
        ingredients: [
        "2 cups mixed vegetables (bell peppers, broccoli, carrots)",
        "1 cup tofu, cubed",
        "2 tbsp soy sauce",
        "1 tbsp sesame oil",
        "2 cloves garlic, minced",
        "1 tsp ginger, grated",
        "Salt and pepper to taste",
        ],
        instructions: [
        "Heat sesame oil in a large pan over medium heat.",
        "Add garlic and ginger, sauté for 1 minute.",
        "Add tofu and cook until golden brown.",
        "Add mixed vegetables and stir-fry for 5-7 minutes.",
        "Pour in soy sauce and season with salt and pepper.",
        "Serve hot over rice or noodles.",
        ],
        },
        ];
        // TODO: Create a function to display the recipes in a grid layout
        function displayRecipes(recipes) {
        // SEO-friendly: Dynamically generate recipe cards for better user engagement
        const container = document.getElementById("recipe-container");
        container.innerHTML = "";
        recipes.forEach((recipe) => {
        const recipeCard = document.createElement("div");
        recipeCard.className =
        "recipe-card relative overflow-hidden rounded-md shadow-md hover:shadow-lg transition-shadow duration-300";
        const image = document.createElement("img");
        image.src = recipe.image;
        image.alt = recipe.title;
        image.className =
        "w-full h-48 object-cover rounded-t-md transition-transform duration-300 transform scale-100 hover:scale-105";
        const overlay = document.createElement("div");
        overlay.className =
        "recipe-overlay absolute bottom-0 left-0 right-0 bg-gradient-to-b from-transparent to-black p-4 text-white opacity-0 hover:opacity-100 transition-opacity duration-300 flex flex-col justify-end rounded-b-md";
        const title = document.createElement("h3");
        title.className = "recipe-title text-lg font-semibold mb-1";
        title.textContent = recipe.title;
        const category = document.createElement("p");
        category.className = "recipe-category text-gray-300 text-sm";
        category.textContent = recipe.category;
        overlay.appendChild(title);
        overlay.appendChild(category);
        recipeCard.appendChild(image);
        recipeCard.appendChild(overlay);
        recipeCard.addEventListener("click", () => showRecipeDetails(recipe)); // Added click event
        container.appendChild(recipeCard);
        });
        }
        function showRecipeDetails(recipe) {
        const modal = document.createElement("div");
        modal.className =
        "fixed inset-0 bg-opacity-50 flex justify-center items-center z-50 backdrop-blur-md";
        const modalContent = document.createElement("div");
        modalContent.className =
        "bg-white rounded-lg p-6 w-full max-w-2xl shadow-xl transform transition-transform duration-300 scale-95 hover:scale-100";
        const title = document.createElement("h2");
        title.className =
        "text-3xl font-semibold mb-4 text-gray-800 border-b border-gray-200 pb-2";
        title.textContent = recipe.title; // SEO-friendly: Use descriptive headings
        const image = document.createElement("img");
        image.src = recipe.image;
        image.alt = recipe.title;
        image.className = "w-full h-64 object-cover rounded-md mb-6";
        const ingredientsTitle = document.createElement("h3");
        ingredientsTitle.className = "text-lg font-semibold mb-2 text-gray-700";
        ingredientsTitle.textContent = "Ingredients:";
        const ingredientsList = document.createElement("ul");
        ingredientsList.className = "list-disc list-inside mb-4 space-y-2";
        recipe.ingredients.forEach((ingredient) => {
        const li = document.createElement("li");
        li.textContent = ingredient; // SEO-friendly: Use structured data
        ingredientsList.appendChild(li);
        });
        const instructionsTitle = document.createElement("h3");
        instructionsTitle.className = "text-lg font-semibold mb-2 text-gray-700";
        instructionsTitle.textContent = "Instructions:";
        const instructionsList = document.createElement("ol");
        instructionsList.className = "list-decimal list-inside space-y-2";
        recipe.instructions.forEach((instruction) => {
        const li = document.createElement("li");
        li.innerHTML = instruction.replace(
        /(\w+)/g,
        '$1'
        );
        instructionsList.appendChild(li);
        });
        const closeButton = document.createElement("button");
        closeButton.className =
        "bg-amber-500 text-white py-3 px-6 rounded-full hover:bg-amber-600 transition duration-300 mt-8 font-semibold";
        closeButton.textContent = "Close";
        closeButton.addEventListener("click", () => document.body.removeChild(modal));
        modalContent.appendChild(title);
        modalContent.appendChild(image);
        modalContent.appendChild(ingredientsTitle);
        modalContent.appendChild(ingredientsList);
        modalContent.appendChild(instructionsTitle);
        modalContent.appendChild(instructionsList);
        modalContent.appendChild(closeButton);
        modal.appendChild(modalContent);
        document.body.appendChild(modal);
        }
        function filterRecipes(query) {
        const lowerCaseQuery = query.toLowerCase();
        return recipes.filter((recipe) => {
        return (
        recipe.title.toLowerCase().includes(lowerCaseQuery) ||
        recipe.ingredients.some((ingredient) =>
        ingredient.toLowerCase().includes(lowerCaseQuery)
        ) ||
        recipe.category.toLowerCase().includes(lowerCaseQuery)
        );
        });
        }
        document.addEventListener("DOMContentLoaded", () => {
        displayRecipes(recipes);
        const searchInput = document.getElementById("search-input");
        const searchButton = document.getElementById("search-button");
        searchButton.addEventListener("click", () => {
        const query = searchInput.value.trim();
        const results = filterRecipes(query);
        const resultsContainer = document.getElementById("search-results");
        resultsContainer.innerHTML = "";
        if (results.length === 0) {
        resultsContainer.innerHTML =
        "

        No recipes found.

        ";
        } else {
        displayRecipes(results);
        }
        });
        searchInput.addEventListener("keypress", (event) => {
        if (event.key === "Enter") {
        searchButton.click();
        }
        });
        });
        const year = new Date().getFullYear();
        document.getElementById("year").textContent = year;



        Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
        53 min
      • Build a Stunning Portfolio Website with Tailwind CSS & JavaScript – Step-by-Step Tutorial (2025)

        ✅ No frameworks✅ Clean UI with Tailwind✅ Smooth animations & mobile-friendly design

        Whether you're a beginner or brushing up your skills, this project is the perfect way to practice frontend fundamentals.

        🔔 Subscribe for more tutorials and real-world projects!📁 Project files & resources: [Insert GitHub or website link]

        In this web development project you will learn how to create a Portfolio website using Tailwind CSS and JavaScript, complete responsive website, dropdown navigation menu, dark mode theme.

        🔥 Become a channel member and get full access to all my web development courses: https://www.youtube.com/playlist?list=UUMOx8iaEliW-CFrS0t9KHisTw

        📚GET ULTIMATE COURSES BUNDLES: https://norbert-bm-s-school.teachable.com/

        -------------------------------------------------------------------------------------------------

        ------------------------------------------------------------------------------------------------- 👉 Full Source Code: https://github.com/NorbertBM/learn-web-development-for-beginners-.git

        -------------------------------------------------------------------------------------------------

        #WebDevelopment #JavaScript #TailwindCSS #BeginnerProjects



        Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
        44 min
      • Create a Message Pop-Up Modal with JavaScript and Tailwind CSS

        In this project, we will build a message pop-up modal using JavaScript and Tailwind CSS. This project is part of my "Learn Web Development From the Beginning" series, where we progressively create real-world projects with HTML, CSS, JavaScript, and Tailwind.

        🔥 Become a channel member and get full access to all my web development courses: https://www.youtube.com/playlist?list=UUMOx8iaEliW-CFrS0t9KHisTw

        📚GET ULTIMATE COURSES BUNDLES: https://norbert-bm-s-school.teachable.com/

        You’ll learn how to:

        * Create a hidden modal

        * Toggle modal visibility with JavaScript

        * Send and validate a message input

        * Close the modal when clicking outside or on a cancel button

        Step 1: Set Up the Basic Project Structure

        * Create a new folder for your project.

        * Inside, create:

        * index.html

        * style.css (optional if you want custom styles)

        * script.js

        * Link TailwindCSS via CDN in your HTML file.

        Message Modal

        Step 2: Build the Modal Structure (HTML)

        Create the modal structure inside the . Initially, the modal should be hidden.

        Open Message Modal

        Send a Message
        Send
        Cancel

        Step 3: Handle the Modal with JavaScript

        In script.js, write the logic to open, close, and send messages.

        // Select Elements

        const modal = document.getElementById('modal');
        const messageButton = document.getElementById('message-button');
        const sendButton = document.getElementById('send-button');
        const closeButton = document.getElementById('close-button');
        const messageInput = document.getElementById('modal-input');
        // Toggle Modal Visibility
        function toggleModal() {
        modal.classList.toggle('hidden');
        }
        // Open Modal
        messageButton.addEventListener('click', toggleModal);
        // Close Modal on Cancel
        closeButton.addEventListener('click', toggleModal);
        // Close Modal When Clicking Outside
        modal.addEventListener('click', function (event) {
        if (event.target === modal) {
        toggleModal();
        }
        });
        // Send Message
        sendButton.addEventListener('click', function () {
        if (messageInput.value.trim() === '') {
        alert('Please enter a message.');
        return;
        }
        alert(`Message sent: ${messageInput.value}`);
        messageInput.value = ''; // Clear input
        toggleModal(); // Close modal
        });

        Step 4: (Optional) Enable Dark Mode Toggle

        Add a dark mode toggle button if you want to enable Tailwind’s dark mode classes dynamically.

        Final Result

        * Click the "Open Message Modal" button ➔ Modal opens.

        * Type a message and click Send ➔ Shows an alert and closes the modal.

        * Click Cancel or click outside the modal ➔ Closes the modal.

        Congratulations! 🎉 You now have a fully functioning, stylish message modal!

        Complete Source Code: https://github.com/NorbertBM/learn-web-development-for-beginners-.git



        Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
        30 min
      • Tailwind CSS 4.1 Offers EXCITING New Features For Developers

        🔧 Getting Started: Setup Tailwind CSS 4.1 Without a Build Tool

        To keep things simple, we’ll use Tailwind via the CDN—no frameworks, no build tools.

        Tailwind 4.1 Demo

        You can now use all of Tailwind’s new features right in your HTML.

        🎨 1. Drop Shadow with Color

        Standard shadows often fall flat, especially in dark mode. Tailwind 4.1 adds color drop shadows to give your elements more punch.

        💡 Example:

        Colorful Drop Shadow

        To control intensity, use shade values like drop-shadow-red-500, drop-shadow-blue-300, etc.

        ✨ 2. Text Shadows (with Color!)

        Text shadows bring another layer of depth, especially on headings and banners.

        💡 Example:

        Spooky Red Glow

        You can go from text-shadow-2xs to text-shadow-lg, and add color variants like text-shadow-blue-400.

        🖼️ 3. Mask Utilities for Images

        You can now mask images or elements using directional gradients.

        💡 Example:

        This creates a soft fade from bottom to top or vice versa. You can tweak directions with classes like mask-top, mask-left, mask-right.

        ⚠️ Mask gradients might look different in dark mode.

        ⚙️ 4. Seamless Dark Mode

        Tailwind 4.1 improves dark mode handling—just use the dark: prefix, no extra configuration needed.

        💡 Example:

        Dark Mode Ready

        ✅ Other Notable Improvements

        * Text wrapping control via overflow-wrap

        * Improved browser compatibility

        * Less need for configuration files

        * CSS @import now works for simpler integrations

        📹 Video Description (for YouTube)

        Tailwind CSS 4.1 is packed with awesome new features—from colored drop shadows and text shadows to masking utilities and dark mode improvements.

        In this video, we:

        ✅ Set up Tailwind 4.1 without build tools

        ✅ Explore drop shadows with color

        ✅ Try out text shadows (yes, with color!)

        ✅ Add image masks using mask-gradient

        ✅ Tweak dark mode designs easily

        🙌 Conclusion

        Tailwind CSS 4.1 brings subtle but powerful tools to elevate your designs. Whether you're building a dark mode dashboard or fine-tuning text styling, there's a feature here for you.

        👉 Which feature are you most excited about? Let me know in the comments or over on YouTube!



        Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
        7 min
      • 🚀 Tailwind CSS Crash Course

        🔧 What is Tailwind CSS?

        Tailwind is a utility-first CSS framework. Instead of writing custom CSS, you use predefined classes to build your UI quickly.

        Promotions👇

        👨‍🏫Ultimate CSS Frameworks Course Bundle Promo : https://norbert-bm-s-school.teachable.com/p/landingpage

        👨‍🏫Master Tailwind CSS: A Beginner’s Guide to Modern Web Design Course Promo: https://www.udemy.com/course/master-tailwind-css-a-beginners-guide-to-modern-web-design/?couponCode=DAYONE

        ✅ Why Tailwind?

        * Fast to build UIs

        * Responsive by default

        * No need to name CSS classes

        * Easy to customize with config files

        Description

        In this tutorial, you'll learn how to create a modern and responsive profile card using Tailwind CSS. This card will include a profile picture, name, job title, description, and interactive buttons. Additionally, we'll implement a dark mode toggle to enhance the user experience. Follow this step-by-step guide to create a sleek profile card for your portfolio or project.

        Here's a short project perfect for teaching a Tailwind CSS crash course: a Responsive Profile Card with Dark Mode Toggle.

        This shows off:

        * Tailwind’s utility classes

        * Responsive design

        * Flexbox

        * Dark mode support

        Custom styles using @apply (optional)

        🧪 Mini Project: Responsive Profile Card + Dark Mode

        🔧 Tools Used

        Tailwind via CDN (for simplicity)

        Vanilla HTML/JS

        Responsive layout

        Dark mode toggle (uses class="dark")

        💡 What You’ll Learn

        * Layout with Flex

        * Utility classes for spacing, colors, borders, and text

        * Responsive design with md:, lg:

        * Dark mode using dark: classes

        * Simple interactivity with JS

        Step 1: Setup Your Project

        * Create a new folder for your project.

        * Inside the folder, create an index.html file.

        * Add the Tailwind CSS CDN to your project for quick setup.

        Step 2: HTML Structure

        Open index.html and add the following code:

        Tailwind Profile Card

        John Doe

        Frontend Developer

        Creating modern UIs and delightful user experiences.

        Follow
        Message
        Toggle Dark Mode

        Step 3: Key Features of the Code

        * Dark Mode SupportThe dark class is added to the tag to enable dark mode.A button toggles the dark class dynamically using JavaScript.

        * Responsive DesignThe card is centered using Tailwind's flex, justify-center, and items-center utilities.The card adjusts to different screen sizes with max-w-sm and w-full.

        * Profile Card StylingThe card has a modern look with rounded corners (rounded-2xl), shadows (shadow-xl), and padding (p-6).The profile picture is styled with rounded-full and a border.

        * Interactive ButtonsButtons have hover effects for better interactivity using hover:bg-blue-700 and hover:bg-gray-700.

        Step 4: Customizing the Card

        Replace the profile picture URL (https://i.pravatar.cc/150?img=12) with your own image.Update the name, job title, and description to match your profile.Modify the button links (href="#") to point to your social media or contact pages.

        Step 5: Testing the Dark Mode

        Open theindex.html file in your browser.Click the "Toggle Dark Mode" button to switch between light and dark themes.Observe how the colors and styles adapt seamlessly.

        GitHub Repository

        https://github.com/NorbertBM/learn-web-development-for-beginners-.git

        Conclusion

        Congratulations! You've successfully created a responsive profile card with Tailwind CSS and implemented dark mode support. This card is perfect for showcasing your profile on a personal website or portfolio. Feel free to experiment with Tailwind's utilities to further customize the design.

        Happy coding!



        Get full access to Norbert’s Web Dev School at norbertbmwebdev.substack.com/subscribe
        28 min

      About Weekly Code Quickies

      From the publisher's feed

      Weekly Code Quickies is a podcast designed for programmers and developers of all skill levels. Each episode is a bite-sized, quick-hit of valuable information and tips on a specific programming…