A Beginner’s Guide to Building Your First React App (With Code)

Let’s make something cool together! Today we’re going to build a super fun little app called “Starlight Composer”. It creates twinkling stars in your browser background based on where you click. Sounds awesome, right? But first things first.

So what is React anyway?

Imagine building websites like regular HTML and CSS stuff. That’s fine for simple pages. Now imagine those pages need to change when the user clicks or moves their mouse – that’s where we often use JavaScript (let’s call it JS). Building cool, interactive web apps usually needs a lot of JavaScript code.

React is basically just one part of all this stuff you see on websites these days. Think of it as a really good set of building blocks specifically for making user interfaces (UIs) with JS. It helps manage how the page looks and updates based on actions, like clicks or button presses.

So points to remember:

  • React is a JavaScript library.
  • It helps you build user interfaces from small parts called components.
  • A component is a function that returns HTML‐like code called JSX.
  • The browser updates only the parts that change. That makes React fast.

Why should we care about React?

React makes things easier to build complex apps that feel alive. It breaks down the page into smaller parts called components (like building lego sets). Each component can handle its own look and feel (CSS) and do its own tasks using JavaScript.

How It Differs From Plain JS

  • In plain JavaScript you select elements and change them by hand.
  • With React you describe the state—what the screen should show.
  • React handles the DOM updates for you.

React has a great potential to polish your app. You can learn it yourself or find a reliable agency that offers react software development services. In this tutorial, we are going to explain how you can build your first react web app. This will give you an idea whether it’s easier to learn or just get away by hiring someone temporarily to complete your project.

What we are going to make will look like this. Those star kind of things will appear as you click. You can click once for small and click multiple times to make it big.

starlight composer

Let’s build Out Starlight Composer step by step

Our “Starlight Composer” app is all about one main part: App.jsx. We will use React to create a dynamic background with stars and also shows the sun or moon depending on which mode you choose!

First things first: Installing Node.js

You need to get the JavaScript powerhouse called Node.js onto your computer. Go to its official website – it’s pretty straightforward, I promise. There they usually have two versions highlighted: LTS (which stands for Long-Term Support) and Current. Pick the LTS version ’cause that’s the stable, reliable one everyone likes.

When you download it, just run the installer like you would any other program. It handles everything behind the scenes for you – no need to worry about tricky details or hidden setup steps. And guess what? The Node.js installer always includes something really important called npm (Node Package Manager). Think of npm as your package delivery service specifically for Node stuff.

Then, setting up React

Now that you have Node and npm sorted, it’s time to bring in React itself. This is done using a command-line tool – basically, the built-in program on your Mac or the Command Prompt (Windows) or PowerShell (if you’re feeling fancy). Open that up:

On PC (Windows): Open either Command Prompt or PowerShell.

On Mac: Fire up your Terminal.

Go to the folder where you want the create this project, e.g.

cd Desktop/Project

On windows it will be changed to (cd Desktop\Project)

1. Now run these commands

npm create vite@latest starlight-composer -- --template react
cd starlight-composer
npm install
  • Replace the files Vite gives you with the ones we will write.
  • Start the dev server:
npm run dev
  • It start the server, probably at http://localhost:5173/ which you can copy from terminal and open in the browser. You will see a simple Vite + React page which may look similar or different.
vite react

2. Use Visual Studio or any other to Edit codes

  • Open starlight-composer folder in the code editor.
  • Inside src folder you will find App.css and App.jsx that we will modify

3. The CSS File, Part 1

Create src/App.css. Paste the first block:

body {
  margin: 0;
  overflow: hidden;
  font-family: 'Segoe UI', Tahoma, sans-serif;
}

.sky {
  position: relative;
  width: 100vw;
  height: 100vh;
  cursor: none;
}
  • body removes scroll bars.
  • .sky fills the window and hides the cursor.

4. Night And Day Styles

Add:

.sky.night {
  background: radial-gradient(circle at center, #0c1445, #000814);
}

.sky.day {
  background: linear-gradient(to bottom, #87ceeb, #b0e2ff);
}
  • Night shows a dark radial glow.
  • Day shows a blue gradient.

5. Heading And Stars

h1 {
  text-align: center;
  color: rgba(255, 249, 230, 0.85);
  padding: 15px 0;
  margin: 0;
  font-weight: 300;
  letter-spacing: 3px;
  text-shadow: 0 0 15px rgba(255, 255, 255, 0.5);
  pointer-events: none;
}

.star {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  animation: twinkle infinite ease-in-out;
}
  • The title floats over the sky.
  • Each star is a circle that twinkles.

The twinkle keyframes sit lower in the file. We will add them soon.

6. Cursor And Click Glow

.cursor {
  position: absolute;
  width: 25px;
  height: 25px;
  border: 2px solid rgba(255, 255, 255, 0.8);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  box-shadow: 0 0 15px #ffffff;
  animation: pulse 2s infinite;
  z-index: 100;
}

.click-glow {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 70%);
  pointer-events: none;
  animation: expand 0.3s forwards;
  z-index: 90;
}
  • The fake cursor glows and pulses.
  • A quick ring expands when you click.

7. Control Buttons

.controls {
  position: absolute;
  top: 20px;
  right: 20px;
  display: flex;
  gap: 10px;
  z-index: 50;
}

.mode-toggle,
.clear-btn {
  background: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: white;
  padding: 8px 15px;
  border-radius: 20px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s;
  z-index: 50;
}

.mode-toggle:hover,
.clear-btn:hover {
  background: rgba(255, 255, 255, 0.25);
}

.sky.day .mode-toggle,
.sky.day .clear-btn {
  color: #000;          /* looks black in daylight */
  border-color: rgba(0, 0, 0, 0.2);
  background: rgba(255, 255, 255, 0.7);
}
  • Buttons sit in the top-right corner.
  • In day mode the text turns dark. The user asked for black; #000 gives that look.

8. Sun And Moon

.celestial {
  top: 15% !important;
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transition: all 2s ease;
}

.sun {
  background: radial-gradient(circle, #ffd700 30%, #ffa500 100%);
  box-shadow: 0 0 80px 40px rgba(255, 165, 0, 0.6);
}

.moon {
  background: radial-gradient(circle, #e6e6e6 30%, #a9a9a9 100%);
  box-shadow: 0 0 60px 20px rgba(230, 230, 230, 0.6);
}
  • celestial is a base class.
  • .sun glows orange; .moon glows silver.

Finish the CSS with mobile tweaks and the keyframes: (We will complete this later witch final code)

@media (max-width: 768px) { /* ... */ }

@keyframes twinkle { /* ... */ }
@keyframes pulse   { /* ... */ }
@keyframes expand  { /* ... */ }

9. The JavaScript File, Part 1

Create src/App.jsx. Begin:

import { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [stars, setStars] = useState([]);
  const [cursor, setCursor] = useState({ x: 0, y: 0 });
  const [clickEffect, setClickEffect] = useState(false);
  const [isDay, setIsDay] = useState(false);
  const [celestialBody, setCelestialBody] = useState(null);
  • React stores data in state.
  • stars holds every star object.
  • cursor tracks mouse position.
  • clickEffect toggles the ring.
  • isDay switches the sky.
  • celestialBody describes the sun or moon.

10. Listen For Mouse Move

  useEffect(() => {
    const handleMove = (e) => setCursor({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handleMove);
    return () => window.removeEventListener('mousemove', handleMove);
  }, []);
  • useEffect runs after the first render.
  • We store the listener and remove it on cleanup.

11. Show Sun Or Moon

  useEffect(() => {
    if (isDay) {
      setCelestialBody({
        type: 'sun',
        size: Math.min(window.innerWidth, window.innerHeight) * 0.15
      });
    } else {
      setCelestialBody({
        type: 'moon',
        size: Math.min(window.innerWidth, window.innerHeight) * 0.1
      });
    }
  }, [isDay]);
  • The effect runs when isDay changes.
  • We pick a size that fills 15 % of the short edge for the sun and 10 % for the moon.

12. Make A Star Object

  const createStar = (x, y) => {
    const sizes  = [2, 3, 4, 5, 6];
    const colors = ['#ffffff', '#fefcd7', '#d7fdff', '#ffebd7'];
    const glows  = ['#ffffff', '#ffffa8', '#a8feff', '#ffd8a8'];

    return {
      id: Date.now() + Math.random(),
      x,
      y,
      size: sizes[Math.floor(Math.random() * sizes.length)],
      color: colors[Math.floor(Math.random() * colors.length)],
      glow: glows[Math.floor(Math.random() * glows.length)],
      duration: (Math.random() * 3 + 2).toFixed(1)
    };
  };
  • Each star gets an id, position, size, color, glow, and twinkle speed.

13. Handle Clicks

  const handleSkyClick = (e) => {
    if (!isDay) {
      setClickEffect(true);
      setTimeout(() => setClickEffect(false), 300);
      setStars([...stars, createStar(e.clientX, e.clientY)]);
    }
  };

  const clearSky = (e) => {
    e.stopPropagation();
    setStars([]);
  };
  • At night a click drops a star.
  • The ring flashes for 0.3 s.
  • clearSky wipes the array.

14. Render The Scene

  return (
    <div
      className={`sky ${isDay ? 'day' : 'night'}`}
      onClick={handleSkyClick}
    >
      <div className="controls">
        <button className="mode-toggle" onClick={() => setIsDay(!isDay)}>
          {isDay ? 'Night Mode' : 'Day Mode'}
        </button>
        <button className="clear-btn" onClick={clearSky}>
          Clear Sky
        </button>
      </div>

      <h1>Starlight Composer</h1>
  • className changes the CSS theme.
  • The toggle button flips to black text during daytime, thanks to the .sky.day styles.

Continue:

      {!isDay && stars.map(star => (
        <div
          key={star.id}
          className="star"
          style={{
            left: star.x,
            top: star.y,
            width: `${star.size}px`,
            height: `${star.size}px`,
            backgroundColor: star.color,
            boxShadow: `0 0 ${star.size * 3}px ${star.size}px ${star.glow}`,
            animationDuration: `${star.duration}s`
          }}
        />
      ))}
  • We skip star render in day mode.

Add the sun or moon, the fake cursor, and the glow:

      {celestialBody && (
        <div
          className={`celestial ${celestialBody.type}`}
          style={{
            width: `${celestialBody.size}px`,
            height: `${celestialBody.size}px`,
            top: '10%',
            left: isDay ? '10%' : '90%'
          }}
        />
      )}

      <div
        className="cursor"
        style={{ left: cursor.x, top: cursor.y }}
      />

      {clickEffect && (
        <div
          className="click-glow"
          style={{ left: cursor.x, top: cursor.y }}
        />
      )}
    </div>
  );
}

export default App;

15. Run And Play

  • Save all files.
  • The browser refreshes.
  • Move the mouse—see the glowing ring.
  • Click at night—stars appear and twinkle.
  • Click Day Mode—the sky turns blue, the button text looks black, the sun slides in.
  • Click Clear Sky—stars disappear.

That is it. You built an interactive scene with just React and CSS.

Complete Code

src/App.css (replace entire existing code with this)

body {
  margin: 0;
  overflow: hidden;
  font-family: 'Segoe UI', Tahoma, sans-serif;
}

.sky {
  position: relative;
  width: 100vw;
  height: 100vh;
  cursor: none;
}

.sky.night {
  background: radial-gradient(circle at center, #0c1445, #000814);
}

.sky.day {
  background: linear-gradient(to bottom, #87ceeb, #b0e2ff);
}

h1 {
  text-align: center;
  color: rgba(255, 249, 230, 0.85);
  padding: 15px 0;
  margin: 0;
  font-weight: 300;
  letter-spacing: 3px;
  text-shadow: 0 0 15px rgba(255, 255, 255, 0.5);
  pointer-events: none;
}

.star {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  animation: twinkle infinite ease-in-out;
}

@keyframes twinkle {
  0%, 100% {
    opacity: 0.6;
    transform: translate(-50%, -50%) scale(0.8);
  }
  50% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.2);
  }
}

.cursor {
  position: absolute;
  width: 25px;
  height: 25px;
  border: 2px solid rgba(255, 255, 255, 0.8);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  box-shadow: 0 0 15px #ffffff;
  animation: pulse 2s infinite;
  z-index: 100;
}

@keyframes pulse {
  0% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 0.7;
  }
  50% {
    transform: translate(-50%, -50%) scale(1.3);
    opacity: 0.4;
  }
  100% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 0.7;
  }
}

.click-glow {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 70%);
  pointer-events: none;
  animation: expand 0.3s forwards;
  z-index: 90;
}

@keyframes expand {
  to {
    width: 120px;
    height: 120px;
    opacity: 0;
  }
}

.controls {
  position: absolute;
  top: 20px;
  right: 20px;
  display: flex;
  gap: 10px;
  z-index: 50;
}

.mode-toggle,
.clear-btn {
  background: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: white;
  padding: 8px 15px;
  border-radius: 20px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s;
  z-index: 50;
}

.mode-toggle:hover,
.clear-btn:hover {
  background: rgba(255, 255, 255, 0.25);
}

.sky.day .mode-toggle,
.sky.day .clear-btn {
  color: #000;
  border-color: rgba(0, 0, 0, 0.2);
  background: rgba(255, 255, 255, 0.7);
}

.celestial {
  top: 15% !important;
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  transition: all 2s ease;
}

.sun {
  background: radial-gradient(circle, #ffd700 30%, #ffa500 100%);
  box-shadow: 0 0 80px 40px rgba(255, 165, 0, 0.6);
}

.moon {
  background: radial-gradient(circle, #e6e6e6 30%, #a9a9a9 100%);
  box-shadow: 0 0 60px 20px rgba(230, 230, 230, 0.6);
}

@media (max-width: 768px) {
  .controls {
    top: 10px;
    right: 10px;
    flex-direction: column;
  }

  .celestial {
    top: 20% !important;
    left: 90% !important;
  }

  .sky.day .celestial {
    left: 10% !important;
  }
}

src/App.jsx

import { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [stars, setStars] = useState([]);
  const [cursor, setCursor] = useState({ x: 0, y: 0 });
  const [clickEffect, setClickEffect] = useState(false);
  const [isDay, setIsDay] = useState(false);
  const [celestialBody, setCelestialBody] = useState(null);

  useEffect(() => {
    const handleMove = (e) => setCursor({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handleMove);
    return () => window.removeEventListener('mousemove', handleMove);
  }, []);

  useEffect(() => {
    if (isDay) {
      setCelestialBody({
        type: 'sun',
        size: Math.min(window.innerWidth, window.innerHeight) * 0.15
      });
    } else {
      setCelestialBody({
        type: 'moon',
        size: Math.min(window.innerWidth, window.innerHeight) * 0.1
      });
    }
  }, [isDay]);

  const createStar = (x, y) => {
    const sizes = [2, 3, 4, 5, 6];
    const colors = ['#ffffff', '#fefcd7', '#d7fdff', '#ffebd7'];
    const glows = ['#ffffff', '#ffffa8', '#a8feff', '#ffd8a8'];

    return {
      id: Date.now() + Math.random(),
      x,
      y,
      size: sizes[Math.floor(Math.random() * sizes.length)],
      color: colors[Math.floor(Math.random() * colors.length)],
      glow: glows[Math.floor(Math.random() * glows.length)],
      duration: (Math.random() * 3 + 2).toFixed(1)
    };
  };

  const handleSkyClick = (e) => {
    if (!isDay) {
      setClickEffect(true);
      setTimeout(() => setClickEffect(false), 300);
      setStars([...stars, createStar(e.clientX, e.clientY)]);
    }
  };

  const clearSky = (e) => {
    e.stopPropagation();
    setStars([]);
  };

  return (
    <div
      className={`sky ${isDay ? 'day' : 'night'}`}
      onClick={handleSkyClick}
    >
      <div className="controls">
        <button className="mode-toggle" onClick={() => setIsDay(!isDay)}>
          {isDay ? 'Night Mode' : 'Day Mode'}
        </button>
        <button className="clear-btn" onClick={clearSky}>
          Clear Sky
        </button>
      </div>

      <h1>Starlight Composer</h1>

      {!isDay &&
        stars.map((star) => (
          <div
            key={star.id}
            className="star"
            style={{
              left: star.x,
              top: star.y,
              width: `${star.size}px`,
              height: `${star.size}px`,
              backgroundColor: star.color,
              boxShadow: `0 0 ${star.size * 3}px ${star.size}px ${star.glow}`,
              animationDuration: `${star.duration}s`
            }}
          />
        ))}

      {celestialBody && (
        <div
          className={`celestial ${celestialBody.type}`}
          style={{
            width: `${celestialBody.size}px`,
            height: `${celestialBody.size}px`,
            top: '10%',
            left: isDay ? '10%' : '90%'
          }}
        />
      )}

      <div
        className="cursor"
        style={{ left: cursor.x, top: cursor.y }}
      />

      {clickEffect && (
        <div
          className="click-glow"
          style={{ left: cursor.x, top: cursor.y }}
        />
      )}
    </div>
  );
}

export default App;

Save the codes, reload the webpage, start clicking on the screen in Night Mode to see the twinkling stars.

Enjoy your first React creation!