Skip to content

Project Setup: Local-First Warehouse Monorepo #1

@AliiiBenn

Description

@AliiiBenn

Local-First Warehouse Monorepo Setup

Overview

This monorepo serves as the core for a local-first warehouse management system using Electron and web technologies with TanStack.

Tech Stack

  • Monorepo: Turbo + pnpm workspaces
  • Framework: React + electron-vite
  • Routing: TanStack Router
  • Data Fetching: TanStack Query
  • State Management: Zustand
  • UI: shadcn/ui + Tailwind CSS
  • Testing: Vitest (unit) + Playwright (e2e)
  • CI/CD: Husky (git hooks) + Changesets (versioning)

Project Structure

monorepo/
├── .husky/                     # Git hooks
│   ├── pre-commit
│   └── commit-msg
│
├── .changeset/
│   └── config.json
│
├── apps/
│   ├── web/
│   │   ├── vite.config.ts
│   │   ├── tailwind.config.ts
│   │   └── package.json
│   │
│   └── desktop/
│       ├── electron.vite.config.ts
│       ├── electron-builder.json
│       └── package.json
│
├── packages/
│   ├── core/
│   │   ├── tsconfig.json
│   │   └── package.json
│   │
│   ├── local-first/
│   │   ├── tsconfig.json
│   │   └── package.json
│   │
│   ├── stores/
│   │   ├── tsconfig.json
│   │   └── package.json
│   │
│   └── config/
│       ├── tsconfig.base.json
│       ├── eslint.config.js
│       ├── vitest.config.ts
│       └── prettier.config.js
│
├── tests/e2e/
│   └── playwright.config.ts
│
├── turbo.json
├── tsconfig.json
├── package.json
└── .env.example

Turbo Configuration

turbo.json

{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "out/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "typecheck": {
      "dependsOn": ["^typecheck"]
    },
    "test": {
      "dependsOn": ["^test"],
      "inputs": ["src/**/*.ts", "src/**/*.tsx", "test/**/*.ts"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "clean": {
      "cache": false
    }
  }
}

Package Scripts

Each package should have these scripts:

{
  "scripts": {
    "build": "tsc && vite build",
    "dev": "vite dev",
    "lint": "eslint src/",
    "typecheck": "tsc --noEmit",
    "test": "vitest run",
    "clean": "rm -rf dist out node_modules"
  }
}

Root scripts:

{
  "scripts": {
    "dev": "turbo dev",
    "build": "turbo build",
    "lint": "turbo lint",
    "typecheck": "turbo typecheck",
    "test": "turbo test",
    "clean": "turbo clean"
  }
}

Husky Configuration

Installation

pnpm dlx husky init

.husky/pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm lint-staged

.husky/commit-msg

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx --no -- commitlint --edit "${1}"

lint-staged.config.js

export default {
  '*.{ts,tsx}': ['eslint --fix', 'vitest --run --passWithNoTests'],
  '*.{json,css,md}': ['prettier --write']
}

commitlint.config.js

export default {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert']
    ],
    'type-case': [2, 'always', 'lower-case'],
    'subject-full-stop': [2, 'never', '.'],
    'subject-empty': [2, 'never']
  }
}

Changesets Configuration

Installation

pnpm add -Dw @changesets/cli
pnpm changeset init

.changeset/config.json

{
  "$schema": "https://unpkg.com/@changesets/cli@2/schema.json",
  "changelog": "@changesets/cli/changelog",
  "commit": false,
  "fixed": [],
  "linked": [],
  "access": "restricted",
  "baseBranch": "main",
  "updateInternalDependencies": "patch"
}

Release Workflow

# .github/workflows/release.yml
name: Release

on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build
        run: pnpm build

      - name: Create changeset
        run: pnpm changeset version

      - name: Publish to npm
        run: pnpm publish -r
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Package Scripts

{
  "scripts": {
    "changeset": "changeset",
    "version": "changeset version",
    "release": "pnpm build && pnpm publish -r"
  }
}

Development Commands

# Install dependencies
pnpm install

# Run all apps in dev mode
turbo dev

# Run specific app
turbo dev --filter=web
turbo dev --filter=desktop

# Lint all packages
turbo lint

# Type check all packages
turbo typecheck

# Run unit tests
turbo test

# Run e2e tests
playwright test

# Build all apps
turbo build

Architecture Patterns

Local-First

  • IndexedDB via Dexie.js
  • Sync engine with operation log pattern
  • Optimistic updates with TanStack Query

Domain-Driven Design (DDD)

  • Entities: Product, Order, Customer, Inventory, Warehouse
  • Value Objects: Money, Address, SKU, Quantity
  • Repository interfaces in packages/core/src/domain/repositories
  • Domain services: InventoryService, OrderService, PricingService

State Management

  • TanStack Query: Server state, caching, mutations, optimistic updates
  • Zustand: UI state (sidebar, theme, modals, notifications)

Getting Started

  1. Clone the repository
  2. Run pnpm install
  3. Copy .env.example to .env if needed
  4. Run pnpm dev to start both web and desktop apps

Contributing

  • Create a changeset before committing: pnpm changeset
  • Follow conventional commits
  • All PRs require lint, typecheck, and tests to pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions