Developing Internal Tools with Tooljet
Tooljet is an open-source low-code platform for building internal tools. Positioned as a more flexible Retool alternative with fully open source and self-hosted deployment.
Differences from Alternatives
| Tooljet | Appsmith | Retool | |
|---|---|---|---|
| Open-source | Yes (AGPL) | Yes (Apache) | No |
| Self-hosted | Yes | Yes | Paid |
| Mobile layout | Yes | Limited | No |
| Built-in DB | TooljetDB (PG) | No | No |
| Custom components | React components | JS components | JS components |
Installation
# Docker
docker run \
-p 80:80 \
-p 443:443 \
-v tooljet_data:/var/lib/postgresql/13/main \
tooljet/tooljet-ce:latest
# production docker-compose
services:
tooljet:
image: tooljet/tooljet-ce:EE-LTS-latest
environment:
TOOLJET_DB: tooljet_db
TOOLJET_DB_USER: postgres
TOOLJET_DB_PASS: password
TOOLJET_DB_HOST: postgres
SECRET_KEY_BASE: "your-secret-key-base"
LOCKBOX_MASTER_KEY: "your-lockbox-key"
ports:
- "80:80"
depends_on:
- postgres
Components and Data
Tooljet works through a visual editor with drag-and-drop. Database/API queries are created in the "Query Manager" panel and bound to components via {{ queries.queryName.data }}.
// Tooljet RunJS Query
// Data validation and transformation
const users = queries.getUsers.data;
return users
.filter(u => u.created_at > moment().subtract(30, 'days').toISOString())
.map(u => ({
...u,
fullName: `${u.first_name} ${u.last_name}`,
registrationAge: moment(u.created_at).fromNow()
}));
Mobile Layout
Tooljet supports a separate layout for mobile devices—you can create a version of the tool for managers on smartphones.
Custom React Components
// Custom component in Tooljet
function CustomComponent({ data, updateData, height, width }) {
const [selected, setSelected] = useState(null);
return (
<div style={{ height, width }}>
<CustomChart
data={data.chartData}
onSelect={(item) => {
setSelected(item);
updateData({ selectedItem: item });
}}
/>
</div>
);
}
Timeline
Basic tool — 2–4 days. Complex with custom components — 1–2 weeks.







