This document explains everything about your project in simple language. You will learn:
- What each folder and file does
- How the app flows from start to finish
- Why we use React and TypeScript
- How the countdown and background selector work
- How to run, debug, and extend the app
If you read this once, you will understand the whole project.
- Shows a live countdown to May 30 (your concert date).
- Updates every second: days, hours, minutes, seconds.
- Lets you choose a background image from a dropdown.
- Remembers your background choice using localStorage.
- React makes UI state easy. State is the data that changes over time (like seconds ticking or a selected background).
- When state changes, React re-renders the UI automatically. You do not update the DOM by hand.
- React components are small, reusable pieces. This app has a main
Appcomponent and a tinyTimeBoxcomponent.
In short: React saves you from manual DOM work and gives you a clean structure.
- TypeScript adds types to JavaScript. Types help you catch mistakes early.
- Example: If a function expects a
Datebut you pass a string, TypeScript warns you. - Types make code more readable and safer, especially as the app grows.
- Vite is a fast development server and build tool.
- It gives instant reloads and a simple build command.
- It is modern and works great with React + TypeScript.
countdown/
├─ index.html # HTML page that loads your React app
├─ package.json # Scripts and dependencies
├─ vite.config.ts # Vite configuration
├─ tsconfig.json # Root TypeScript config (uses references)
├─ tsconfig.app.json # TS config for the app code (browser side)
├─ tsconfig.node.json # TS config for node-side (Vite config)
├─ public/ # Static assets served as-is
│ └─ vite.svg
└─ src/
├─ main.tsx # App entry: mounts React into the page
├─ App.tsx # Main React component (countdown + backgrounds)
├─ styles.css # App styling (layout + visuals)
├─ index.css (optional) # Template CSS (not used by our main path)
├─ App.css (optional) # Template CSS (not used by our main path)
└─ assets/
└─ react.svg # Template asset (from Vite)
Notes:
- Only
main.tsx,App.tsx, andstyles.cssare important for the app logic and UI. tsconfig.*.jsonfiles control TypeScript behavior (explained below).
- Browser loads
index.html. index.htmlincludes<script type="module" src="/src/main.tsx"></script>.src/main.tsximports React andApp, finds the DOM element with idroot, and renders<App />inside it.App.tsxsets up:- The concert date (May 30, current year or next if already past).
- A timer that ticks every second to update the countdown.
- The background selector and localStorage persistence.
styles.cssgives the page layout, glass card style, and responsive grid.
- It imports React, ReactDOM,
App, and the global CSS. - It calls
ReactDOM.createRoot(...).render(...)to mount the app into the div with idroot. - It uses
React.StrictModeto help catch common problems during development.
In short: main.tsx is the one-time startup file.
App.tsx does the main work. Important parts:
-
Target date logic
- We get today’s year.
- Build May 30 of this year.
- If today is after May 30, we set the target to next year.
-
Countdown logic
- A function
getTimeRemaining(targetDate)returns days, hours, minutes, seconds. - It clamps negative values to zero (so UI never shows negative time).
- A
setInterval(viauseEffect) runs every second to force a re-render.
- A function
-
Background selection
- A list
BACKGROUNDSholds options (id, label, image URL). - We keep the selected background id in React state.
- We save the id to
localStorageso your choice persists after refresh.
- A list
-
Rendering
- A full-screen background image + a dark overlay (scrim) for readability.
- A centered “card” that shows the title, target year, and the 4 time boxes.
- A dropdown to change background and a Reset button.
-
Accessibility and readability
- The countdown grid uses clear labels.
- Numbers are padded to 2 digits for hours/minutes/seconds.
Main ideas:
- Full-height layout, centered content.
- A background image layer and a semi-transparent overlay to keep text readable.
- A glass-like card with rounded corners and blur.
- A responsive grid for the 4 time boxes (2 columns on small screens).
- Focus styles for keyboard accessibility.
You can tweak colors and fonts here.
-
tsconfig.json(root)- Uses
referencesto point attsconfig.app.jsonandtsconfig.node.json. - This is a “project references” setup. Each referenced config must be buildable.
- Uses
-
tsconfig.app.json- For browser app code (files in
src/). - Has
"composite": trueand emits declaration files (not JS) to satisfy the references rule. - Sets
jsx: "react-jsx"and other strict/lint-related options.
- For browser app code (files in
-
tsconfig.node.json- For Node context (like
vite.config.ts). - Also
"composite": trueand emits declaration files only.
- For Node context (like
Why declarations only? TypeScript requires referenced projects to be “emittable.” We emit type declarations instead of JS because Vite will handle JS bundling.
- Install Node.js (LTS is recommended). On Windows, you can use
nvm-windowsto manage versions. - In the project folder, run:
npm install npm run dev
- Open the URL printed in the terminal (usually
http://localhost:5173).
Build for production:
npm run build
npm run preview- We compute
difference = targetDate - nowin milliseconds. - Convert milliseconds into days/hours/minutes/seconds using division/modulo.
- Recalculate every second with
setIntervaland React state to trigger a re-render. - If the target date is past,
differenceis negative; we clamp to 0 and show a small message.
- Background choices live in a constant array
BACKGROUNDSwith image URLs. - The dropdown’s value is kept in React state
backgroundId. - When the value changes, we save it to
localStorageunder the keycountdown:bg. - On startup, we read from
localStorageto restore the user’s choice.
To add a new background:
- Add a new item to
BACKGROUNDSinApp.tsx:{ id: 'my-photo', label: 'My Photo', url: 'https://...' }
- It will show automatically in the dropdown.
-
Change the target date:
- In
App.tsx, we set the date to May 30 by default. You can change it to a fixed date:const concertDate = new Date('2026-05-30T00:00:00');
- Or add a date picker component and store the result in state.
- In
-
Change fonts/colors:
- Edit CSS variables in
:rootinsidestyles.css.
- Edit CSS variables in
-
Add more UI (like event name or location):
- Add new elements inside the
.carddiv ofApp.tsx.
- Add new elements inside the
-
TypeScript reference errors (
composite,noEmit):- Keep
"composite": trueintsconfig.app.jsonandtsconfig.node.json. - Do not set
"noEmit": truein referenced projects; use declaration-only emit instead.
- Keep
-
Duplicate symbol errors (e.g.,
Identifier 'App' has already been declared):- Ensure
src/main.tsxmounts the app only once and importsApponly once. - Ensure
src/App.tsxexports a single defaultAppcomponent.
- Ensure
-
Blank page:
- Check browser console for errors.
- Make sure
index.htmlhas<div id="root"></div>andmain.tsxtargets#root.
- Component: A reusable piece of UI in React (function that returns JSX).
- State: Data that changes over time and triggers re-render.
- Props: Input parameters to a component.
- JSX: HTML-like syntax inside JavaScript/TypeScript used by React.
- Render: When React turns components into real DOM elements on the page.
- Created a React + TypeScript app using Vite structure.
- Implemented
App.tsxwith:- Target date calculation (May 30, this year or next).
getTimeRemainingto compute days/hours/minutes/seconds.- One-second ticking using
setIntervalin auseEffect. - Background selector with localStorage persistence.
- Responsive and accessible UI in
styles.css.
- Cleaned up duplicate components and duplicate entry-point code.
- Fixed TypeScript project references:
- Added
"composite": truetotsconfig.app.jsonandtsconfig.node.json. - Replaced
noEmitwith declaration-only emission to satisfy references.
- Added
- Open
src/App.tsxand read top-to-bottom. - Change the target date and see how UI updates.
- Add a new background option and select it.
- Change styles in
src/styles.css(e.g., colors, padding). - Create a new component (e.g.,
EventName.tsx) and render it inApp.
Each change gives you quick feedback in the browser.
- Start dev server:
npm run dev - Build for production:
npm run build - Preview production build:
npm run preview
- Add a custom date picker so you can count down to anything.
- Allow users to upload their own background image.
- Add timezone selection.
- Animate the time boxes when values change.
You now have a solid base to learn and build more. Have fun coding!