PROJECT_IGNITER Docs

Developer Docs

Implementation deep-dive for contributors extending Project Igniter.

Tech Stack

LayerTechnology
Desktop FrameworkTauri v2
FrontendReact 19, TypeScript
State ManagementZustand 5
Build ToolVite 7
StylingTailwind CSS 4
Drag & Drop@dnd-kit/sortable
BackendRust (Tauri commands)

Architecture Overview

Project Igniter has three core modules that map to its three-phase pipeline:

Phase 1: Project Analyzer

Scans project directories to suggest starter workflows. Not yet implemented — planned for future releases.

Phase 2: Workflow Composer

React frontend with Zustand state store. Composes workflow trees that are persisted as JSON. The UI communicates with Tauri commands for file I/O.

Phase 3: Script Forge

Pure TypeScript module. Reads workflow JSON, walks the tree recursively, and emits Bash/PowerShell source code. No Tauri dependency — testable standalone.

Workflow Data Model

The core data structure is a recursive tree. The TypeScript types live insrc/features/workflow/types/workflow.ts:

interface Workflow {
id: string;
name: string;
description?: string;
environment?: string;
steps: Step[]; // ordered by index
}

type Step = InputStep | InformationStep | CheckStep
| ConditionStep | CommandStep | ChoiceStep
| FileStep | FlowStep | OSBranchStep;

Each step has a unique id (UUID), a name, and a type. Steps with branches contain nested Workflow objects. The branching step types are:

  • checkonSuccess / onFailure
  • conditiononTrue / onFalse
  • commandonSuccess / onFailure
  • fileonSuccess / onFailure
  • osBranchmacos / linux / windows

Workflow Persistence

Workflows are stored on disk as JSON files. The structure under .project-igniter/:

.project-igniter/
  workflows.json # Index of all workflows, projects, envs
  workflows/
    <uuid>.json # Individual workflow

The workflows.json index schema:

{
  schema: 1,
  defaultProject: "root",
  standalone: [],
  projects: {
    root: {
      path: ".",
      defaultEnv: "dev",
      environments: {
        dev: { id: "<uuid>" }
      }
    }
  }
}

Converter Internals

The converter is a pure-function pipeline. It does not depend on Tauri, React, or Node.js APIs — it takes workflow data in, returns source code out. This makes it testable and portable.

Entry Point

convertAll() in src/converter/index.tstakes the workflows path, index, and workflow map. It iterates over every project/environment pair, calls the Bash and PowerShell walkers, and returns a flat array of{path, content} objects. It also generates orchestrator and root wrapper scripts.

Tree Walkers

bash.ts and powershell.tseach implement a recursive tree walk. The key functions:

  • generateWorkflow(workflow, followUpId)Linear walk of steps, determines NEXT for each. The followUpId is what runs after the sub-workflow completes.
  • generateStep(step, nextId, entries)Dispatches to the per-step converter, appends the case entry with NEXT set to nextId.
  • generateBranchingStep(step, nextId, entries)Handles steps with branches: recursively walks sub-workflows, generates the branching logic (if/else), and sets NEXT based on outcome.

Step Converter Contract

Each file in src/converter/steps/ exports two functions:

export function toBash(step: StepType): string;
export function toPowerShell(step: StepType): string;

Each function returns only the body of the step — what commands to execute. It does not handle setting NEXT, input persistence, or branching logic — those are handled by the main tree walker.

Adding a New Step Type

To extend Project Igniter with a new step type:

  1. 1.Define the type in src/features/workflow/types/workflow.ts — extend the Step union.
  2. 2.Add it to the step type registry in the Workflow Composer UI so it appears in the "Add Step" menu.
  3. 3.Create src/converter/steps/<name>.ts with toBash() and toPowerShell().
  4. 4.Add a case in bash.ts and powershell.ts in generateStep() or generateBranchingStep().
  5. 5.Add a properties editor component in src/features/properties/components/.

If the step type branches (has sub-workflows), implement it in generateBranchingStep(). If it's linear (like input or information), use generateStep().