π Folder Structure (React + Vite)
When you create a new React app (especially with Vite), this is what your folder typically looks like:
π§ Basic Folder Layout:
<div class="infographic-reactfolders" id="rf">
<style>
.infographic-reactfolders {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-deep: #1942a8;
--accent-soft: #e3ebfd;
--line: #ddd6c9;
--radius: 8px;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
--mono-font: 'IBM Plex Mono', monospace;
max-width: 880px;
padding: 2rem 0;
margin: 0 auto;
box-sizing: border-box;
background: transparent;
color: var(--ink);
font-family: var(--body-font);
}
.infographic-reactfolders[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #13171f;
--paper-alt: #1c212b;
--accent: #5b8def;
--accent-deep: #8fb4ff;
--accent-soft: #20293f;
--line: #2c313d;
}
.infographic-reactfolders * { box-sizing: border-box; }
.rf-eyebrow {
font-family: var(--mono-font); font-size: 0.72rem; letter-spacing: 0.1em;
text-transform: uppercase; color: var(--accent); margin: 0 0 0.45rem;
display: flex; align-items: center; justify-content: center; gap: 0.4rem;
}
.rf-eyebrow::before { content: ""; width: 14px; height: 2px; background: var(--accent); display: inline-block; }
.rf-title {
font-family: var(--display-font); font-size: clamp(1.5rem, 4vw, 2.3rem); text-align: center;
margin: 0 0 0.55rem; line-height: 1.12; letter-spacing: -0.01em;
}
.rf-sub {
color: var(--ink-soft); font-size: 0.95rem; max-width: 500px; line-height: 1.55; margin: 0 auto 1.8rem;
text-align: center;
}
/* ===== VS Code mockup β fixed dark theme regardless of page mode ===== */
.rf-window {
border-radius: 8px; overflow: hidden; box-shadow: 0 16px 40px -14px rgba(0,0,0,0.45);
border: 1px solid #1e1e1e; font-family: var(--mono-font);
}
.rf-titlebar {
background: #323233; display: flex; align-items: center; padding: 0.5rem 0.8rem; position: relative;
}
.rf-dots { display: flex; gap: 0.4rem; }
.rf-dots span { width: 10px; height: 10px; border-radius: 50%; display: block; }
.rf-dots span:nth-child(1) { background: #ff5f56; }
.rf-dots span:nth-child(2) { background: #ffbd2e; }
.rf-dots span:nth-child(3) { background: #27c93f; }
.rf-titlebar-text {
position: absolute; left: 50%; transform: translateX(-50%); font-size: 0.72rem; color: #cccccc;
}
.rf-body { display: flex; height: 380px; }
.rf-activitybar { width: 44px; background: #333333; display: flex; flex-direction: column; align-items: center; padding-top: 0.7rem; gap: 1.1rem; flex-shrink: 0; }
.rf-activitybar svg { width: 20px; height: 20px; }
.rf-activity-icon { opacity: 0.55; }
.rf-activity-icon.is-on { opacity: 1; border-left: 2px solid #ffffff; margin-left: -2px; padding-left: 2px; }
.rf-sidebar { width: 220px; background: #252526; flex-shrink: 0; overflow-y: auto; border-right: 1px solid #1e1e1e; }
.rf-sidebar-head {
font-size: 0.68rem; font-weight: 700; letter-spacing: 0.06em; color: #bbbbbb; padding: 0.65rem 0.9rem 0.4rem;
}
.rf-row {
display: flex; align-items: center; gap: 0.35rem; width: 100%; background: none; border: none;
color: #cccccc; font: inherit; font-size: 0.78rem; padding: 0.28rem 0.6rem 0.28rem 0.7rem;
cursor: pointer; text-align: left; border-left: 2px solid transparent; white-space: nowrap;
}
.rf-row:hover { background: #2a2d2e; }
.rf-row:focus-visible { outline: 1px solid #0078d4; outline-offset: -1px; }
.rf-row.is-selected { background: #37373d; border-left-color: #0078d4; }
.rf-row.rf-l1 { padding-left: 1.6rem; }
.rf-row.rf-l2 { padding-left: 2.5rem; }
.rf-row.rf-dim { color: #6f6f6f; font-style: italic; }
.rf-chevron { width: 12px; flex-shrink: 0; text-align: center; color: #8b8b8b; font-size: 0.6rem; }
.rf-folder-icon { width: 14px; height: 12px; flex-shrink: 0; }
.rf-badge {
width: 16px; height: 16px; border-radius: 3px; flex-shrink: 0; display: flex; align-items: center;
justify-content: center; font-size: 0.5rem; font-weight: 700; color: #1a1a1a; line-height: 1;
}
.rf-editor { flex: 1; background: #1e1e1e; display: flex; flex-direction: column; min-width: 0; }
.rf-tabbar { display: flex; background: #252526; border-bottom: 1px solid #1e1e1e; }
.rf-tab {
display: flex; align-items: center; gap: 0.4rem; background: #1e1e1e; color: #d4d4d4; font-size: 0.75rem;
padding: 0.5rem 0.9rem; border-right: 1px solid #1e1e1e; border-top: 2px solid #0078d4;
}
.rf-tab .rf-badge, .rf-tab .rf-folder-icon { width: 14px; height: 14px; font-size: 0.48rem; }
.rf-breadcrumb { font-size: 0.68rem; color: #808080; padding: 0.4rem 1rem; border-bottom: 1px solid #262626; }
.rf-content { flex: 1; padding: 1.6rem 1.5rem; overflow-y: auto; }
.rf-content-icon { width: 46px; height: 46px; margin-bottom: 0.9rem; }
.rf-content-icon .rf-badge { width: 46px; height: 46px; border-radius: 8px; font-size: 1rem; }
.rf-content-icon .rf-folder-icon { width: 42px; height: 34px; }
.rf-content-name { font-size: 1.05rem; color: #ffffff; margin: 0 0 0.35rem; word-break: break-all; }
.rf-content-kind {
display: inline-block; font-size: 0.65rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
color: #9a9a9a; background: #2d2d2d; border-radius: 3px; padding: 0.2rem 0.5rem; margin-bottom: 0.9rem;
}
.rf-content-desc { font-size: 0.85rem; color: #cccccc; line-height: 1.6; max-width: 46ch; font-family: var(--body-font); }
@media (max-width: 620px) {
.rf-sidebar { width: 165px; }
.rf-body { height: 420px; }
.rf-row { font-size: 0.72rem; }
}
@media (max-width: 480px) {
.rf-activitybar { display: none; }
}
.rf-takeaway {
margin-top: 1.6rem; padding: 0.95rem 1.2rem; background: var(--accent-soft);
border-left: 3px solid var(--accent); border-radius: 4px; font-size: 0.9rem; color: var(--ink); line-height: 1.5;
}
.rf-takeaway b { color: var(--accent-deep); }
@media (prefers-reduced-motion: reduce) {
.infographic-reactfolders *, .infographic-reactfolders *::before, .infographic-reactfolders *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
<div class="rf-eyebrow">Project Anatomy</div>
<h1 class="rf-title">Inside a React App</h1>
<p class="rf-sub">Click any file or folder in the sidebar to see what it's for.</p>
<div class="rf-window">
<div class="rf-titlebar">
<div class="rf-dots"><span></span><span></span><span></span></div>
<div class="rf-titlebar-text">my-react-app β Visual Studio Code</div>
</div>
<div class="rf-body">
<div class="rf-activitybar">
<svg class="rf-activity-icon is-on" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="4" width="7" height="7" rx="1" stroke="#fff" stroke-width="1.6"/><rect x="14" y="4" width="7" height="7" rx="1" stroke="#fff" stroke-width="1.6"/><rect x="3" y="15" width="7" height="7" rx="1" stroke="#fff" stroke-width="1.6"/><rect x="14" y="15" width="7" height="7" rx="1" stroke="#fff" stroke-width="1.6"/></svg>
<svg class="rf-activity-icon" viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="10" cy="10" r="6.5" stroke="#fff" stroke-width="1.6"/><line x1="15" y1="15" x2="20" y2="20" stroke="#fff" stroke-width="1.6" stroke-linecap="round"/></svg>
<svg class="rf-activity-icon" viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="6" cy="6" r="2.3" stroke="#fff" stroke-width="1.5"/><circle cx="6" cy="18" r="2.3" stroke="#fff" stroke-width="1.5"/><circle cx="18" cy="12" r="2.3" stroke="#fff" stroke-width="1.5"/><path d="M8 7l8 4M8 17l8-4" stroke="#fff" stroke-width="1.4"/></svg>
</div>
<div class="rf-sidebar">
<div class="rf-sidebar-head">EXPLORER</div>
<button class="rf-row" data-id="root" type="button"><span class="rf-chevron">βΎ</span><svg class="rf-folder-icon" viewBox="0 0 16 13" aria-hidden="true"><path d="M1 1h5l1.3 1.6H15v9.4H1z" fill="#dcb67a"/></svg><span>MY-REACT-APP</span></button>
<button class="rf-row rf-l1 rf-dim" data-id="node_modules" type="button"><span class="rf-chevron">βΈ</span><svg class="rf-folder-icon" viewBox="0 0 16 13" aria-hidden="true"><path d="M1 1h5l1.3 1.6H15v9.4H1z" fill="#6f6f6f"/></svg><span>node_modules</span></button>
<button class="rf-row rf-l1" data-id="public" type="button"><span class="rf-chevron">βΈ</span><svg class="rf-folder-icon" viewBox="0 0 16 13" aria-hidden="true"><path d="M1 1h5l1.3 1.6H15v9.4H1z" fill="#dcb67a"/></svg><span>public</span></button>
<button class="rf-row rf-l1 is-selected" data-id="src" type="button"><span class="rf-chevron">βΎ</span><svg class="rf-folder-icon" viewBox="0 0 16 13" aria-hidden="true"><path d="M1 1h5l1.3 1.6H15v9.4H1z" fill="#dcb67a"/></svg><span>src</span></button>
<button class="rf-row rf-l2" data-id="appjsx" type="button"><span class="rf-chevron"></span><span class="rf-badge" style="background:#29b6f6;">JSX</span><span>App.jsx</span></button>
<button class="rf-row rf-l2" data-id="mainjsx" type="button"><span class="rf-chevron"></span><span class="rf-badge" style="background:#29b6f6;">JSX</span><span>main.jsx</span></button>
<button class="rf-row rf-l2" data-id="indexcss" type="button"><span class="rf-chevron"></span><span class="rf-badge" style="background:#42a5f5;">#</span><span>index.css</span></button>
<button class="rf-row rf-l1" data-id="gitignore" type="button"><span class="rf-chevron"></span><span class="rf-badge" style="background:#9e9e9e;">GI</span><span>.gitignore</span></button>
<button class="rf-row rf-l1" data-id="packagejson" type="button"><span class="rf-chevron"></span><span class="rf-badge" style="background:#fbc02d;">{ }</span><span>package.json</span></button>
<button class="rf-row rf-l1" data-id="viteconfig" type="button"><span class="rf-chevron"></span><span class="rf-badge" style="background:#646cff; color:#fff;">β‘</span><span>vite.config.js</span></button>
<button class="rf-row rf-l1" data-id="readme" type="button"><span class="rf-chevron"></span><span class="rf-badge" style="background:#42a5f5;">Mβ</span><span>README.md</span></button>
</div>
<div class="rf-editor">
<div class="rf-tabbar" id="rfTabbar"></div>
<div class="rf-breadcrumb" id="rfBreadcrumb"></div>
<div class="rf-content" id="rfContent"></div>
</div>
</div>
</div>
<div class="rf-takeaway"><b>Only <code style="font-family:var(--mono-font)">src</code> is yours to edit</b> β everything else is config, tooling, or generated for you.</div>
</div>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@500;600&family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
<script>
(function () {
var root = document.getElementById('rf');
if (!root) return;
/* --- dark mode detection: body attribute > cookie > postMessage > light --- */
function applyDark(dark) {
if (dark) root.setAttribute('data-theme', 'dark');
else root.removeAttribute('data-theme');
}
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') dark = true;
else if (bodyAttr === 'false') dark = false;
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
applyDark(dark);
window.addEventListener('message', function (e) {
if (e.data && e.data.type === 'darkMode') applyDark(!!e.data.value);
});
/* --- file tree data --- */
var items = {
root: { name: 'my-react-app', folder: true, kind: 'Folder', path: ['my-react-app'],
desc: 'Your project root β everything below lives inside here.' },
node_modules: { name: 'node_modules', folder: true, kind: 'Folder', path: ['my-react-app', 'node_modules'],
desc: 'Every installed package, auto-generated by npm. Never edit it by hand, never commit it.' },
public: { name: 'public', folder: true, kind: 'Folder', path: ['my-react-app', 'public'],
desc: "Static files served as-is β favicon, robots.txt, anything that skips bundling." },
src: { name: 'src', folder: true, kind: 'Folder', path: ['my-react-app', 'src'],
desc: "Your actual source code lives here β everything you'll write and edit." },
appjsx: { name: 'App.jsx', badge: 'JSX', color: '#29b6f6', kind: 'JSX File', path: ['my-react-app', 'src', 'App.jsx'],
desc: 'The main component β the root of your whole UI tree.' },
mainjsx: { name: 'main.jsx', badge: 'JSX', color: '#29b6f6', kind: 'JSX File', path: ['my-react-app', 'src', 'main.jsx'],
desc: 'The entry point β renders <App /> into the HTML page.' },
indexcss: { name: 'index.css', badge: '#', color: '#42a5f5', kind: 'CSS File', path: ['my-react-app', 'src', 'index.css'],
desc: 'Global styles that apply across the whole app.' },
gitignore: { name: '.gitignore', badge: 'GI', color: '#9e9e9e', kind: 'Git Config', path: ['my-react-app', '.gitignore'],
desc: 'Tells Git which files to skip β node_modules, build output, and more.' },
packagejson: { name: 'package.json', badge: '{ }', color: '#fbc02d', kind: 'JSON File', path: ['my-react-app', 'package.json'],
desc: 'Project metadata β dependencies, scripts, name, and version.' },
viteconfig: { name: 'vite.config.js', badge: 'β‘', color: '#646cff', textColor: '#fff', kind: 'Config File', path: ['my-react-app', 'vite.config.js'],
desc: 'Configures Vite β plugins, dev server, and build options.' },
readme: { name: 'README.md', badge: 'Mβ', color: '#42a5f5', kind: 'Markdown File', path: ['my-react-app', 'README.md'],
desc: 'Docs for humans β setup steps and notes for the team.' }
};
var rows = root.querySelectorAll('.rf-row');
var tabbar = root.querySelector('#rfTabbar');
var breadcrumb = root.querySelector('#rfBreadcrumb');
var content = root.querySelector('#rfContent');
function iconHTML(item, size) {
if (item.folder) {
return '<svg class="rf-folder-icon" viewBox="0 0 16 13" aria-hidden="true"><path d="M1 1h5l1.3 1.6H15v9.4H1z" fill="#dcb67a"/></svg>';
}
var tc = item.textColor || '#1a1a1a';
return '<span class="rf-badge" style="background:' + item.color + '; color:' + tc + ';">' + item.badge + '</span>';
}
function select(id) {
var item = items[id];
if (!item) return;
rows.forEach(function (r) { r.classList.toggle('is-selected', r.getAttribute('data-id') === id); });
tabbar.innerHTML = '<div class="rf-tab">' + iconHTML(item) + '<span>' + item.name + '</span></div>';
breadcrumb.textContent = item.path.join(' \u203a ');
content.innerHTML =
'<div class="rf-content-icon">' + iconHTML(item) + '</div>' +
'<h2 class="rf-content-name">' + item.name + '</h2>' +
'<span class="rf-content-kind">' + item.kind + '</span>' +
'<p class="rf-content-desc">' + item.desc + '</p>';
}
rows.forEach(function (r) {
r.addEventListener('click', function () { select(r.getAttribute('data-id')); });
});
select('src');
})();
</script>1οΈβ£ node_modules/
Purpose: Contains all the packages your project depends on.
Do Not Touch Directly β This is managed by
npmoryarn.
2οΈβ£ public/
Main File:
index.htmlWhat it does:
This is the base HTML file.
React mounts your app into the
<div id="root"></div>insideindex.html.
Can include favicon, images, etc., accessible via
/public/filename.
3οΈβ£ src/ (Main Working Area)
index.js or main.jsx
Purpose: Entry point of the app.
What it contains:
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<App />);
App.js
Purpose: Main component that holds your entire app layout.
What it contains:
Other components are imported here.
Routes (if using React Router).
function App() { return ( <div> <Navbar /> <Home /> <Footer /> </div> ); } export default App;
components/
Purpose: Reusable UI pieces (buttons, navbars, cards, etc.)
Examples:
components βββ Navbar.js βββ Footer.js βββ Button.js
pages/
Purpose: Full pages/views like Home, About, Contact.
These usually contain multiple components.
Example:
pages/ βββ Home.js βββ About.js βββ Contact.js
assets/
Purpose: Store images, videos, fonts, or other static resources used in the app.
Example:
assets/ βββ logo.png βββ bg-video.mp4
App.css or styles/
Purpose: Styling the
App.jsor shared styles.You can create a full
styles/folder if you want to keep modular CSS files.
4οΈβ£ package.json
Purpose: Describes the project and its dependencies.
Shows which packages are installed, and which scripts are available (
npm start,npm run build, etc.).
5οΈβ£ .gitignore
Purpose: Lists files/folders to ignore in Git (e.g.,
node_modules/,.env)
6οΈβ£ README.md
Purpose: A markdown file to describe your project, installation steps, usage instructions, etc.
7οΈβ£ vite.config.js / webpack.config.js
If you're using Vite or Webpack, these files define the bundling, plugins, alias paths, etc.
β¨ JSX Syntax (JavaScript XML)
JSX allows you to write HTML-like code inside JavaScript β it's what makes React easy and intuitive.
β Example:
function Welcome() {
return <h1>Hello, React!</h1>;
}π§ JSX Basics:
JSX looks like HTML but is not exactly HTML.
You must return only one parent element.
return ( <div> <h1>Hello</h1> <p>Welcome to React</p> </div> );Use
classNameinstead ofclass(JSX uses JavaScript conventions).All tags must be properly closed:
β
<img src="logo.png" />β
<img src="logo.png">You can embed JavaScript using curly braces:
const name = "xyz"; return <h2>Welcome, {name}!</h2>;