Workflow automation platform built on Frappe framework with React frontend.
Backend: Python 3.10+, Frappe 15.0+, MariaDB 10.6+, Redis Frontend: React 18, TypeScript, Vite, TanStack Router/Query, Zustand, ReactFlow, Tailwind CSS
hazelnode/
├── hazelnode/ # Python backend (Frappe app)
│ ├── hazelnode/doctype/ # Data models (workflows, nodes, logs)
│ ├── nodes/ # Node implementations
│ │ ├── actions/ # Email, API call, condition, create/update doc, etc.
│ │ ├── triggers/ # Webhook, schedule, document events
│ │ └── __init__.py # Abstract Node base class
│ ├── fixtures/ # Standard node types (JSON)
│ ├── hooks.py # Frappe hooks
│ └── api.py # REST endpoints
├── frontend/ # React app
│ └── src/
│ ├── components/ # UI, nodes, workflows
│ ├── routes/ # TanStack Router pages
│ ├── stores/ # Zustand state (editor.ts)
│ └── queries/ # React Query definitions
├── pyproject.toml # Python config + Ruff settings
└── .pre-commit-config.yaml # Pre-commit hooks
# Tests
bench --site test_site run-tests --app hazelnode
# Frontend dev
cd frontend && npm run dev # Port 8080
cd frontend && npm run build # Build to ../hazelnode/public/frontend/
# Linting
ruff check . # Python lint
ruff format . # Python format
cd frontend && npm run lint # TypeScript lintPython: Ruff formatter/linter. Line length 70, tabs, single quotes. TypeScript: ESLint + Prettier. Strict mode enabled.
Pre-commit hooks auto-run on commit (ruff format, ruff check, import sorting).
- Graph-based execution with context passing between nodes
- Triggers: Schedule (CRON), Document Event, Webhook
- Actions: Email, API Call, Condition, Create/Update Doc, Set Variable, Log, Delay
- Condition nodes return
{branch: 'true'|'false'}for branching
Hazel Workflow- Workflow definition with nodes/connectionsHazel Node- Individual node configHazel Node Type- Node type definitions (fixtures)Hazel Workflow Execution Log- Execution history
- Editor store (Zustand): nodes, edges, flow state
- React Query: server state for workflows/users
- ReactFlow: visual workflow editor
| File | Purpose |
|---|---|
hazelnode/hazelnode/doctype/hazel_workflow/hazel_workflow.py |
Workflow execution logic |
hazelnode/nodes/__init__.py |
Abstract Node base class |
hazelnode/nodes/triggers/hazel_webhook_handler.py |
Webhook handler |
hazelnode/hooks.py |
Frappe hooks, fixtures, routing |
frontend/src/stores/editor.ts |
Zustand editor state |
frontend/src/routes/workflow.$id.tsx |
Workflow editor page |
- Node IDs:
node_${counter}_${timestamp} - Template vars in params:
{{ variable_name }} - API endpoints:
@frappe.whitelist()decorator - Error handling:
frappe.throw()for user errors - Frontend basepath:
/hazelnode
- Triggers on
developbranch push and all PRs - Services: MariaDB 10.6, Redis (ports 13000, 11000)
- Python 3.14, Node 24
- Runs:
bench --site test_site run-tests --app hazelnode
The project includes shadcn MCP server configuration (.mcp.json) for AI-assisted component management. This enables:
- Browse and search shadcn components
- Install components using natural language
- Works with Claude Code, Cursor, and VS Code
Example prompts:
- "Show me all available components in the shadcn registry"
- "Add the button, dialog and card components to my project"
- "Create a contact form using components from the shadcn registry"
Configuration: frontend/components.json (style: new-york, baseColor: slate)