Skip to content

Project Structure

Vite generates a minimal starting structure. For a real app like ZeroBudget you will add more folders. Getting this right before you build saves time refactoring later.

src/
├── assets/
├── App.css
├── App.jsx
├── index.css
└── main.jsx

This works for a counter demo. It does not scale to an app with 10+ components, custom hooks, shared data, and a context layer. Before writing any ZeroBudget code, set up a structure that will grow cleanly.

src/
├── components/
│ ├── MonthNav/
│ │ ├── MonthNav.jsx
│ │ └── MonthNav.css
│ ├── IncomeSection/
│ │ ├── IncomeSection.jsx
│ │ └── IncomeSection.css
│ ├── CategoryCard/
│ │ ├── CategoryCard.jsx
│ │ └── CategoryCard.css
│ ├── TransactionForm/
│ │ ├── TransactionForm.jsx
│ │ └── TransactionForm.css
│ └── TransactionList/
│ ├── TransactionList.jsx
│ └── TransactionList.css
├── context/
│ └── BudgetContext.jsx
├── data/
│ └── defaults.js
├── hooks/
│ ├── useBudget.js
│ └── useLocalStorage.js
├── App.css
├── App.jsx
├── index.css
└── main.jsx

components/ holds every UI component. Each component gets its own folder containing the JSX file and its CSS. Co-locating styles with the component that uses them means you never wonder which CSS file controls a given element.

context/ holds the React Context provider and the useBudgetContext hook. Separating context from components keeps the data layer distinct from the rendering layer.

data/ holds static data that does not change at runtime — in ZeroBudget’s case, the default category list. Keeping it separate makes it easy to find and change without touching component logic.

hooks/ holds custom hooks. Any logic you extract out of a component that uses React hooks lives here. useBudget handles all state and actions; useLocalStorage handles persistence.

React components use PascalCase for both the file name and the function name: CategoryCard.jsx exports function CategoryCard. This is not enforced by JavaScript but is a universal React convention.

Custom hooks use camelCase starting with use: useBudget.js exports function useBudget. The use prefix is required — React’s linter uses it to identify functions that can contain hook calls.

Utility files and data files use camelCase: defaults.js.

  1. In your Vite project, create the folder structure above inside src/.
  2. Create an empty MonthNav.jsx inside src/components/MonthNav/ that exports a placeholder component:
    export default function MonthNav() {
    return <div>Month Nav</div>;
    }
  3. Import and render MonthNav inside App.jsx. Confirm it appears in the browser.
  4. Think about ZeroBudget: which component do you expect to be the most complex? Why?
  • Vite’s default structure is minimal — add folders before building to avoid later refactoring.
  • Each component gets its own folder with a .jsx file and a co-located .css file.
  • Separate context/, data/, and hooks/ folders keep different concerns distinct.
  • Component files and function names use PascalCase. Custom hooks use camelCase starting with use.
  • In the next module you will start building components with props.