Skip to main content
With a workspace initialized, you can now house one or many projects. A project is an application, library, or any buildable unit in your repository. Each project will have its own build layer, personal tasks, and custom configuration.

Declaring a Project in the Workspace

Although a project may exist in your repository, it’s not accessible from moon until it’s been mapped in the projects setting found in .moon/workspace.yml. Let’s say we have a frontend web application called “client” and a backend application called “server”:
.moon/workspace.yml
projects:
  client: 'apps/client'
  server: 'apps/server'
You can now run moon project client and moon project server to display information about each project:
moon project client
If these projects were not mapped, or were pointing to an invalid source, the command would throw an error.
The projects setting also supports a list of globs if you’d prefer to not manually curate the projects list! See the Setup Workspace guide for more details.

Configuring a Project

A project can be configured in two ways:

Global Task Configuration

Through .moon/tasks/**/* config files, which define file groups and tasks that are inherited by matching projects within the workspace. Perfect for standardizing common tasks like linting, typechecking, and code formatting.

Project-Specific Configuration

Through the <project>/moon.yml config file, found at the root of each project, which defines file groups, tasks, dependencies, and more that are unique to that project.
Both config files are optional and can be used separately or together!

Project-Specific Tasks

Let’s configure both the client and server projects with their own build tasks:
apps/client/moon.yml
language: 'javascript'

tasks:
  build:
    command: 'vite build'
    inputs:
      - 'src/**/*'
      - 'index.html'
      - 'vite.config.js'
    outputs:
      - 'dist'
  
  dev:
    command: 'vite dev'
    local: true

Shared Task Configuration

Common tasks that apply to multiple projects can be defined in .moon/tasks/ and inherited by all matching projects:
.moon/tasks/node.yml
tasks:
  format:
    command: 'prettier --check .'
    inputs:
      - 'src/**/*'
      - '.prettierrc'
  
  lint:
    command: 'eslint --no-error-on-unmatched-pattern .'
    inputs:
      - 'src/**/*'
      - '.eslintrc.js'
  
  test:
    command: 'jest --passWithNoTests'
    inputs:
      - 'src/**/*'
      - 'tests/**/*'
      - 'jest.config.js'
  
  typecheck:
    command: 'tsc --build --pretty'
    inputs:
      - 'src/**/*'
      - 'tsconfig.json'
Now all projects with language: 'javascript' will inherit these tasks automatically!

Project Dependencies

If a project depends on another project (e.g., the client depends on a shared UI library), you can declare this relationship:
apps/client/moon.yml
language: 'javascript'

dependsOn:
  - 'ui-library'

tasks:
  build:
    command: 'vite build'
    deps:
      # Run the ui-library build before this build
      - '^:build'
The ^:build target means “run the build task in all projects this project depends on”.

Adding Project Metadata

When utilizing moon in a large monorepo or organization, ownership becomes very important. moon supports the project field within moon.yml to provide metadata:
apps/client/moon.yml
layer: 'application'
language: 'typescript'

project:
  name: 'Client Web App'
  description: 'Customer-facing web application'
  channel: '#frontend-team'
  owner: 'frontend.team'
  maintainers:
    - 'alice.johnson'
    - 'bob.smith'

tasks:
  # ...

Available Metadata Fields

  • layer - The project layer (application, library, tool, etc.)
  • language - The primary programming language
  • project.name - Human-readable project name
  • project.description - Brief description of the project
  • project.channel - Communication channel (e.g., Slack channel)
  • project.owner - Team or individual owner
  • project.maintainers - List of maintainers

File Groups

File groups allow you to group similar file types for reuse across tasks:
apps/client/moon.yml
fileGroups:
  sources:
    - 'src/**/*'
    - 'types/**/*'
  tests:
    - 'tests/**/*'
    - '**/*.test.ts'
  configs:
    - '*.config.js'
    - 'tsconfig.json'

tasks:
  build:
    command: 'webpack build'
    inputs:
      - '@globs(sources)'
      - '@globs(configs)'
    outputs:
      - 'dist'
The @globs(sources) token expands to all files matching the sources file group.

Example: Complete Project Configuration

Here’s a complete example bringing it all together:
apps/web/moon.yml
$schema: 'https://moonrepo.dev/schemas/project.json'

layer: 'application'
language: 'typescript'

project:
  name: 'Web Application'
  description: 'Main customer-facing web application'
  owner: 'platform.frontend'
  maintainers: ['tech-lead']

dependsOn:
  - 'ui-components'
  - 'api-client'

fileGroups:
  sources:
    - 'src/**/*'
  tests:
    - 'tests/**/*'
  configs:
    - '*.config.{js,ts}'
    - 'tsconfig.json'

tasks:
  build:
    command: 'vite build'
    inputs:
      - '@globs(sources)'
      - '@globs(configs)'
    outputs:
      - 'dist'
    deps:
      - '^:build'
  
  dev:
    command: 'vite dev --port 3000'
    local: true
  
  preview:
    command: 'vite preview'
    deps:
      - 'build'

Next Steps

Create a Task

Learn how to configure and optimize tasks

Project Configuration Reference

View all available project configuration options

Build docs developers (and LLMs) love