Skip to content

Codergrounds is a real-time collaborative coding playground featuring a live Monaco editor, peer programming capabilities, and a self-hosted code execution pipeline. Built with React, Express, Socket.io, PostgreSQL, and Docker

Notifications You must be signed in to change notification settings

devnadeemashraf/codergrounds-frontend

Repository files navigation

@codergrounds/frontend

The Client for Codergrounds. Built with React and TypeScript, following a Feature-First Architecture.

🏗️ Architecture

This project follows a Feature-First Architecture that scales with the application by grouping related logic (UI, State, API) together within features, while keeping shared utilities and core infrastructure separate.

Architecture Overview

The architecture is organized into four main layers:

  1. features/ - Feature-based modules (business domain logic)
  2. shared/ - Reusable code with no feature dependencies
  3. services/ - Infrastructure & external integrations
  4. app/ - Application configuration & providers

Folder Structure

src/
├── app/                        # Application configuration & Providers
│   ├── router/                 # Route definitions & Guard wrappers
│   ├── store/                  # Global Redux store configuration
│   ├── providers/              # Context providers (Theme, Toast, etc.)
│   ├── App.tsx                 # Root component
│   └── main.tsx                # Entry point
│
├── features/                   # Feature-based specific modules
│   ├── auth/                   # Authentication Feature
│   │   ├── api/                # RTK Query API definitions
│   │   ├── components/         # Feature-specific UI components
│   │   ├── hooks/              # Feature-specific hooks
│   │   ├── slice/              # Redux slices (state)
│   │   ├── routes/             # Feature internal routes
│   │   └── index.ts            # Public API of the feature
│   │
│   ├── playground/             # Coding Playground Feature
│   │   ├── components/         # Editor, Terminal, FileTree
│   │   ├── services/           # Feature-specific services
│   │   ├── store/              # Playground specific state logic
│   │   └── index.ts
│   │
│   └── user/                   # User Profile/Settings Feature
│
├── shared/                     # Reusable code (No feature dependencies)
│   ├── components/             # UI Kit (Atomic, dumb components)
│   │   ├── ui/                 # Headless UI implementations
│   │   ├── layout/             # Layout components
│   │   └── forms/              # Form primitives
│   ├── hooks/                  # Global hooks
│   ├── utils/                  # Pure utility functions
│   ├── types/                  # Global TypeScript types
│   └── assets/                 # SVGs, Images, Global Styles
│
├── services/                   # Infrastructure & External Integrations
│   ├── api/                    # Base API setup (RTK Query baseQuery)
│   ├── socket/                 # Socket.io singleton & connection management
│   ├── storage/                # LocalStorage/SessionStorage wrappers
│   └── logger/                 # Frontend logger/Analytics wrapper
│
└── config/                     # Environment & Constant configurations
    ├── env.config.ts
    └── breakpoints.config.ts

Key Principles

  1. Feature Isolation: Each feature is self-contained with its own components, state, and API logic
  2. Shared Foundation: shared/ contains only reusable code with no business logic dependencies
  3. Separation of Concerns: Server state (RTK Query) vs Client state (Redux slices)
  4. Single Responsibility: One feature = one business domain
  5. No Cross-Feature Dependencies: Features communicate via global store or shared events

Dependency Flow

app/ (Main Entry)
  ↓
features/ (Auth, Playground, User)
  ↓
shared/ (UI Kit, Utils)  &  services/ (API, Socket)

Dependency Rules:

  • features/ → Can import from shared/ and services/
  • shared/ → Can only import from shared/ or external packages ✅
  • services/ → Can only import from shared/ or external packages ✅
  • app/ → Can import from features/, shared/, and services/
  • NEVER create circular dependencies
  • AVOID direct imports between features

🗂️ State Management

This project uses Redux Toolkit with RTK Query for state management, splitting state into two categories:

Server State (Data)

Managed entirely by RTK Query:

  • Do not manually fetch data in useEffect and store in Redux
  • Use useGetPlaygroundQuery hooks directly in components
  • Cache invalidation tags handle updates
  • API endpoints are defined in features/*/api/

Client State (UI)

Managed by Redux Slices:

  • Examples: "Is Modal Open", "Current Selected File Path", "Terminal History"
  • Located in features/*/slice/
  • Use for UI state that doesn't come from the server

🎨 Styling

We use TailwindCSS v4 for scoped, maintainable styling with BEM (Block Element Modifier) naming convention if using custom css styles.

Responsive Breakpoints

Consistent breakpoints are defined in @/config/breakpoints.config.ts:

  • Mobile (sm): < 640px
  • Tablet (md): 640px - 1023px
  • Desktop (lg): >= 1024px

BEM Naming Convention

All CSS classes in module files must follow the BEM methodology:

  • Block: The main component (e.g., .button, .header)
  • Element: Part of the block, separated by __ (e.g., .button__icon, .header__nav)
  • Modifier: Variation of block/element, separated by -- (e.g., .button--primary, .input__field--error)

⚡ Key Technologies

  • React: UI library with hooks
  • TypeScript: Type-safe development
  • TailwindCSS: CSS Library
  • Redux Toolkit: State management
  • RTK Query: Server state management and data fetching
  • React Router: Client-side routing
  • Socket.io: Real-time collaboration and updates
  • CSS Modules: Scoped component styling
  • Vite: Build tool and dev server
  • Monaco Editor: Code editor component

📜 Scripts

  • pnpm dev: Start development server with hot module replacement
  • pnpm build: Build production bundle to dist/
  • pnpm preview: Preview production build locally
  • pnpm lint: Lint code with ESLint

🚀 Getting Started

  1. Install dependencies: pnpm install
  2. Set up environment variables: Copy .env.example to .env and configure
  3. Start development server: pnpm dev
  4. Open browser: Navigate to http://localhost:5173 (or the port shown in terminal)

🔌 Real-time Communication

Real-time features (collaboration, live updates) are handled via Socket.io:

  • Connection: Established in App.tsx or Auth wrapper using services/socket
  • Global Events: Handled in custom middleware or global hooks
  • Feature Events: Handled inside Feature components using useEffect that listens to the socketService instance

🧪 Testing Strategy

  • Components: React Testing Library - Test behavior, not implementation details
  • Logic: Pure functions in utils/ or complex Redux selectors
  • Integration: Test full feature flows mocking the API via MSW (Mock Service Worker) or simple Redux mocks

About

Codergrounds is a real-time collaborative coding playground featuring a live Monaco editor, peer programming capabilities, and a self-hosted code execution pipeline. Built with React, Express, Socket.io, PostgreSQL, and Docker

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published