Skip to main content

Overview

This guide will help you set up and run the Nadie Sabe Nada Podcast application locally. You’ll go from zero to a fully functional podcast player in just a few minutes.
Make sure you’ve completed the installation steps before proceeding.

Running the Application

1

Start the Development Server

From the project root directory, start the development server:
npm start
The application will automatically:
  • Start the React development server
  • Open your default browser to http://localhost:3000
  • Enable hot module replacement for instant updates
2

Verify the App is Running

You should see the Nadie Sabe Nada podcast player with:
  • A search bar at the top
  • A list of podcast episodes
  • A navigation header
The app will display “Cargando Podcast…” (Loading Podcast…) while fetching episodes from the API.
3

Explore the Features

Try out the core features:
  • Click on any episode to view details
  • Use the play button to start listening
  • Search for episodes using the search bar
  • Navigate to “Último Episodio” (Latest Episode) from the menu

Application Entry Point

The application bootstraps through src/index.js, which sets up the Redux store, React Router, and core providers:
src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { BrowserRouter as Router } from "react-router-dom";
import NavBar from "./components/Header/Header";
import ScrollToTop from "./components/ScrollToTop/ScrollToTop";
import { HelmetProvider } from "react-helmet-async";
import { Provider } from "react-redux";
import { store } from "./store/store";
import { Toaster } from "react-hot-toast";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
    <React.StrictMode>
        <Provider store={store}>
            <Router>
                <NavBar />
                <HelmetProvider>
                    <App />
                    <Toaster />
                </HelmetProvider>
                <ScrollToTop />
            </Router>
        </Provider>
    </React.StrictMode>
);

Understanding the Core App Component

The main App component (src/App.js) handles routing and podcast playback:
src/App.js (excerpt)
import { useEffect } from "react";
import { Routes, Route } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import PodcastList from "./components/PodcastList/PodcastList";
import PodcastDetail from "./components/PodcastDetail/PodcastDetail";
import PersistentPlayer from "./components/PersistentPlayer/PersistentPlayer";
import { fetchPodcasts } from "./store/slices/podcastSlice";

const App = () => {
    const dispatch = useDispatch();
    const { loading, error } = useSelector((state) => state.podcast);
    const { showPlayer } = useSelector((state) => state.player);

    // Fetch podcasts on mount
    useEffect(() => {
        dispatch(fetchPodcasts());
    }, [dispatch]);

    return (
        <div className={styles.container}>
            {/* Search bar, routes, and persistent player */}
        </div>
    );
};

Key Routes

The application provides the following routes:
RouteComponentDescription
/PodcastListHomepage with all episodes
/podcast/:idPodcastDetailIndividual episode details
/ultimo-episodioLastPodcastLatest episode page
/settingsSettingsUser preferences
*NotFound404 error page

Fetching Podcast Data

The app uses Redux Toolkit’s createAsyncThunk to fetch podcast data from the API:
src/store/slices/podcastSlice.js (excerpt)
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

export const fetchPodcasts = createAsyncThunk(
    "podcast/fetchPodcasts",
    async () => {
        const response = await axios.get(
            "https://nsn-podcast-api-rapidapi.netlify.app/podcast"
        );
        return response.data.allEpisodes;
    }
);
The podcast data is stored in Redux state and persisted to localStorage for features like:
  • Favorite episodes
  • Listen-later queue
  • Completed episodes
  • Playback positions

Playing a Podcast Episode

When a user clicks play, the PersistentPlayer component renders with the selected episode:
src/components/PersistentPlayer/PersistentPlayer.jsx (excerpt)
import AudioPlayer from "react-h5-audio-player";
import { motion } from "framer-motion";
import { useDispatch, useSelector } from "react-redux";

const PersistentPlayer = ({ onClose }) => {
    const { currentPodcast, isPlaying } = useSelector((state) => state.player);
    const { playbackTimes, savePlaybackTime } = useSelector(
        (state) => state.audioTime
    );

    // Restore saved playback position
    useEffect(() => {
        if (audioRef.current && currentPodcast) {
            const savedTime = savePlaybackTime 
                ? playbackTimes[currentPodcast.title] || 0 
                : 0;
            audioRef.current.audio.current.currentTime = savedTime;
        }
    }, [currentPodcast]);

    return (
        <motion.div className={styles.persistentPlayer}>
            <AudioPlayer
                src={currentPodcast.audio}
                showJumpControls={true}
                onListen={handleTimeUpdate}
                onEnded={handleEnded}
            />
        </motion.div>
    );
};

Available Scripts

The following npm scripts are available:
npm start
# Runs the app in development mode on http://localhost:3000

Building for Production

1

Create Production Build

Generate an optimized production build:
npm run build
This creates a build/ directory with:
  • Minified JavaScript bundles
  • Optimized CSS
  • Compressed assets
  • Source maps for debugging
2

Test Production Build Locally

You can serve the production build locally using a static server:
npx serve -s build
The app will be available at http://localhost:3000.
3

Deploy to Hosting

Deploy the build/ folder to your preferred hosting platform:
  • Netlify
  • Vercel
  • GitHub Pages
  • AWS S3 + CloudFront
  • Any static hosting service

Environment Variables

Optional environment variables for YouTube integration:
.env (example)
REACT_APP_YT_API_KEY=your_youtube_api_key_here
REACT_APP_CHANNEL_ID=nadie_sabe_nada_channel_id
Environment variables must be prefixed with REACT_APP_ to be accessible in the app.

Testing the Persistent Player

To test the persistent audio player feature:
1

Play an Episode

Click the play button on any episode card
2

Navigate Away

Click on another episode or navigate to a different page
3

Verify Playback Continues

The persistent player should remain visible and continue playing
4

Check Position Saving

Pause the episode, refresh the page, and play again. The player should resume from where you left off.

Local Storage Keys

The app uses localStorage to persist user data:
KeyPurpose
nsnPodcastFavoritesArray of favorited episode titles
nsnPodcastListenLaterArray of listen-later episode titles
nsnPodcastCompletedArray of completed episode titles
nsnPodcastListenedArray of started episode titles
nsnPlayerVolumeSaved player volume (0-1)
audioPlaybackTimesObject mapping episode titles to playback positions

Common Issues

The app fetches data from https://nsn-podcast-api-rapidapi.netlify.app/podcast. If this endpoint is down or slow:
  • Check your internet connection
  • Verify the API endpoint is accessible
  • Check browser console for CORS errors
Common audio playback issues:
  • Check browser console for errors
  • Verify the episode has a valid audio URL
  • Ensure browser autoplay policies aren’t blocking playback
  • Try a different browser
If playback positions aren’t persisting:
  • Check browser localStorage is enabled
  • Verify you’re not in private/incognito mode
  • Check the Redux state in React DevTools

Next Steps

Explore Features

Learn about all available features and how to use them

Component Reference

Dive into the codebase and component documentation

State Management

Learn about Redux state management

Hooks & Utilities

Explore custom hooks and utility functions

Build docs developers (and LLMs) love