Skip to main content

Overview

DevJobs is built with a modern React architecture using Vite as the build tool. The project follows a component-based structure with clear separation of concerns.

Directory Structure

source/
├── public/                 # Static assets served directly
│   ├── background.webp    # Background images
│   └── vite.svg           # Vite logo
├── src/                   # Application source code
│   ├── assets/           # React-imported assets
│   │   └── react.svg
│   ├── components/       # Reusable UI components
│   ├── hooks/           # Custom React hooks
│   ├── pages/           # Page-level components
│   ├── App.jsx          # Root application component
│   ├── App.css          # Global app styles
│   ├── main.jsx         # Application entry point
│   ├── index.css        # Global CSS styles
│   └── data.json        # Static data (legacy/fallback)
├── eslint.config.js      # ESLint configuration
├── vite.config.js        # Vite bundler configuration
├── jsconfig.json         # JavaScript compiler options
├── package.json          # Project dependencies and scripts
└── index.html           # HTML entry point

Component Organization

Components are organized by feature, with each component in its own directory containing all related files:
src/components/
├── ErrorBoundary/
│   ├── ErrorBoundary.jsx
│   ├── ErrorPage.jsx
│   └── ErrorPage.module.css
├── Footer/
│   └── Footer.jsx
├── Header/
│   └── Header.jsx
├── JobCard/
│   ├── JobCard.jsx
│   └── jobCard.module.css
├── JobDetailSkeleton/
│   ├── JobDetailSkeleton.jsx
│   └── JobDetailSkeleton.module.css
├── JobListings/
│   └── JobListings.jsx
├── Link/
│   └── Link.jsx
├── Loading/
│   ├── Loading.jsx
│   └── Loading.module.css
├── PageSkeleton/
│   ├── PageSkeleton.jsx
│   └── PageSkeleton.module.css
├── Pagination/
│   ├── Pagination.jsx
│   └── Pagination.module.css
├── SearchFormSection/
│   └── SearchFormSection.jsx
└── index.js              # Component exports barrel file

Component Structure Convention

Each component follows this pattern:
  • Component directory: Named with PascalCase matching the component name
  • JSX file: Contains the component logic and markup
  • CSS Module (optional): Component-specific styles using .module.css extension
  • Barrel export: All components exported through components/index.js

Pages Structure

Page components represent different routes in the application:
src/pages/
├── 404.jsx              # Not found page
├── Detail.jsx           # Job detail page
├── Detail.module.css    # Detail page styles
├── Home.jsx            # Homepage/landing page
└── Search.jsx          # Job search results page

Custom Hooks

Reusable logic is extracted into custom hooks:
src/hooks/
├── useFilters.js        # Job filtering and pagination logic
├── useRouter.js         # Router utilities
└── useSearchForm.js     # Search form state management

Configuration Files

vite.config.js

Vite configuration with React plugin and path aliases:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': '/src',
    },
  },
})
Key features:
  • React plugin with SWC for faster builds
  • Path alias @/src for cleaner imports

eslint.config.js

ESLint flat config with React-specific rules:
export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{js,jsx}'],
    extends: [
      js.configs.recommended,
      reactHooks.configs.flat.recommended,
      reactRefresh.configs.vite,
    ],
    rules: {
      'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
    },
  },
])
Key rules:
  • React Hooks rules enforcement
  • React Refresh for HMR
  • Allows unused vars starting with uppercase (React components)

jsconfig.json

JavaScript compiler configuration for IDE support:
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src"]
}
Enables path alias autocomplete in editors.

package.json

Project metadata and dependencies:
{
  "name": "02-react",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  }
}

File Naming Conventions

Components

  • Component files: PascalCase (e.g., JobCard.jsx)
  • Component directories: PascalCase matching component name
  • CSS Modules: camelCase or PascalCase with .module.css extension

Hooks

  • Custom hooks: camelCase starting with use (e.g., useFilters.js)

Pages

  • Page components: PascalCase (e.g., Detail.jsx, Search.jsx)
  • Special pages: Numeric for error codes (e.g., 404.jsx)

Styles

  • Global styles: kebab-case (e.g., index.css)
  • Module styles: Component name + .module.css (e.g., jobCard.module.css)

Import Conventions

Path Aliases

Use the @ alias for cleaner imports from src/:
// Good
import { JobCard } from '@/components'
import { useFilters } from '@/hooks/useFilters'

// Avoid
import { JobCard } from '../../components'

Component Imports

Components are exported through a barrel file (components/index.js):
// Import multiple components
import { Header, Footer, JobCard } from '@/components'

// All components are named exports

Build Output

Build artifacts are generated in the dist/ directory:
  • Production-optimized bundles
  • Minified JavaScript and CSS
  • Static assets with hashed filenames
  • Ignored by Git (.gitignore)

Development vs Production

Development Mode

  • Fast HMR (Hot Module Replacement)
  • Source maps enabled
  • React development warnings
  • Run with npm run dev

Production Build

  • Minified and optimized code
  • Tree-shaking for smaller bundles
  • Asset optimization
  • Build with npm run build, preview with npm run preview

Build docs developers (and LLMs) love