Ein Vergleich von Open-Source No- und Low-Code Plattformen die man selber hosten kann.

Die Use Cases

Ich habe mir zwei Use Cases als Ziel gesetzt:

  1. Wir bauen eine Web-App die Daten aus einer API konsumiert und in funktionsgerechten Tabellen darstellt.
  2. Wir importieren Tabellen aus Excel Dateien und wollen diese schick darstellen.

Die Kandidaten

Mit Hilfe von AI und Websuche finden wir mögliche Standardlösungen.

NameErste Bewertung nach HP StudiumLizenzLetzter CommitContributors
BudibaseViele Features in Community Edition gesperrtProprietär2 Tage120
TooljetViele Features in Community Edition gesperrtAGPL-3.0 license2 Tage654
NocobaseEinige Features in Community Edition gesperrtProprietär5 Tage107
AppsmithEinige Features in Community Edition gesperrtApache-2.02 Tage342
BaserowEinige Features in Community Edition gesperrtProprietär2 Tage52
GrommetAnderer Use Case, fällt raus-
SailAnderer Use Case, fällt raus-
rowyAnderer Use Case, fällt raus-
DirectusAnderer Use Case, fällt raus-

Quick-and-Dirty: Live Demos

Wir probieren alle Tools mal kurz aus.

Dazu erstellen wir entsprechende compose Projekte und fahren diese dann auf unserem Server hoch = Live Demo.

Nocobase

Die Einrichtung von Nocobase ist zunächst sehr simpel.

Nach dem ersten Start werden wir vom Login Screen begrüßt. Der voreingestellte User ist:

Email: admin@nocobase.com Password: admin123.

Zumindest das Passwort sollten wir schnell ändern.

Nun sind wir angemeldet und der nüchterne Startbildschirm sieht so aus:

Die Details zur Konfiguration hier im Unterkapitel Setup, im Kapitel Use Cases gucken wir uns das Tool dann genauer an.

Setup

Den Unterordner “storage” legen wir zuvor an.

compose.yml:

services:
    app:
        image: nocobase/nocobase:latest-full
        restart: unless-stopped
        networks:
            - default
            - caddy
        depends_on:
            - postgres
        environment:
            # The application's secret key, used to generate user tokens, etc.
            # If APP_KEY is changed, old tokens will also become invalid.
            # It can be any random string, and make sure it is not exposed.
            - APP_KEY=
            # Database type, supports postgres, mysql, mariadb
            - DB_DIALECT=postgres
            # Database host, can be replaced with the IP of an existing database server
            - DB_HOST=postgres
            # Database port
            - DB_PORT=5432
            # Database name
            - DB_DATABASE=nocobase
            # Database user
            - DB_USER=nocobase
            # Database password
            - DB_PASSWORD=
            # Timezone
            - TZ=Europe/Berlin
        volumes:
            - ./storage:/app/nocobase/storage
        labels:
            - "traefik.enable=true"
            - "traefik.docker.network=caddy"
            - "traefik.http.routers.noco.rule=Host(`nocobase.handtrixxx.com`)"
            - "traefik.http.routers.noco.entrypoints=websecure"
            - "traefik.http.routers.noco.tls.certresolver=letsencrypt"
            - "traefik.http.routers.noco.service=noco"
            - "traefik.http.routers.noco-http.rule=Host(`nocobase.handtrixxx.com`)"
            - "traefik.http.routers.noco-http.entrypoints=web"
            - "traefik.http.routers.noco-http.middlewares=https-redirect"
            - "traefik.http.routers.noco-http.service=noco"
            - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
            - "traefik.http.middlewares.https-redirect.redirectscheme.permanent=true"
            - "traefik.http.services.noco.loadbalancer.server.port=80"
        #ports:
        #    - "13000:80"
        # init: true

    # If using an existing database server, postgres service can be omitted
    postgres:
        image: postgres:16
        restart: unless-stopped
        command: postgres -c wal_level=logical
        environment:
            POSTGRES_USER: nocobase
            POSTGRES_DB: nocobase
            POSTGRES_PASSWORD: 
        volumes:
            - ./storage/db/postgres:/var/lib/postgresql/data
        networks:
            - default
networks:
    caddy:
        external: true

Appsmith

Auch Appsmith lässt sich sehr einfach einrichten.

Nach dem ersten Start werden wir von einem Assistenten begrüßt, über den wir unseren ersten User einrichten.

Direkt danach werden wir schon nach einer Datenquelle zum verbinden gefragt:

Diesen Schritt überspringen wir zunächst.

Anschließend landen wir direkt in einem App Designer:

Die Details zur Konfiguration hier im Unterkapitel Setup, im Kapitel Use Cases gucken wir uns das Tool dann genauer an.

Setup

Den Unterordner “stacks” legen wir zuvor an.

compose.yml

services:
    appsmith:
        image: index.docker.io/appsmith/appsmith-ce
        container_name: appsmith
        #ports:
        #    - "80:80"
        #    - "443:443"
        volumes:
            - ./stacks:/appsmith-stacks
        networks:
            - caddy
        restart: unless-stopped
        labels:
            - com.getarcaneapp.arcane.updater=false
            - "traefik.enable=true"
            - "traefik.docker.network=caddy"
            - "traefik.http.routers.appsmith.rule=Host(`appsmith.handtrixxx.com`)"
            - "traefik.http.routers.appsmith.entrypoints=websecure"
            - "traefik.http.routers.appsmith.tls.certresolver=letsencrypt"
            - "traefik.http.routers.appsmith.service=appsmith"
            - "traefik.http.routers.appsmith-http.rule=Host(`appsmith.handtrixxx.com`)"
            - "traefik.http.routers.appsmith-http.entrypoints=web"
            - "traefik.http.routers.appsmith-http.middlewares=https-redirect"
            - "traefik.http.routers.appsmith-http.service=appsmith"
            - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
            - "traefik.http.middlewares.https-redirect.redirectscheme.permanent=true"
            - "traefik.http.services.appsmith.loadbalancer.server.port=80"
networks:
    caddy:
        external: true

Tooljet

Tooljet bietet viele Optionen zu Einrichtung.

Nach dem ersten Start werden wir von einem Assistenten begrüßt, über den wir unseren ersten User einrichten.

Die UI des System wirkt moderner als z.B. bei Appsmith oder Nocobase und begrüßt uns mit einem Assistenten der uns fragt was wir als nächsten tun wollen:

Die Details zur Konfiguration des Setup hier im Unterkapitel Setup, im Kapitel Use Cases gucken wir uns das Tool dann genauer an.

Setup

Im Endeffekt sind eine compose.yml und eine .env Datei anzulegen, ebenso wie ein Unterordner “postgres_data”.

compose.yml

name: Tooljet app

services:
    tooljet:
        tty: true
        stdin_open: true
        container_name: Tooljet-app
        image: tooljet/tooljet-ce:ce-lts-latest
        platform: linux/amd64
        restart: always
        env_file: .env
        #ports:
        #  - 80:80
        networks:
            - default
            - caddy
        depends_on:
            - postgres
        environment:
            SERVE_CLIENT: "true"
            PORT: "80"
        command: npm run start:prod
        labels:
            - "traefik.enable=true"
            - "traefik.docker.network=caddy"
            - "traefik.http.routers.tooljet.rule=Host(`tooljet.handtrixxx.com`)"
            - "traefik.http.routers.tooljet.entrypoints=websecure"
            - "traefik.http.routers.tooljet.tls.certresolver=letsencrypt"
            - "traefik.http.routers.tooljet.service=tooljet"
            - "traefik.http.routers.tooljet-http.rule=Host(`tooljet.handtrixxx.com`)"
            - "traefik.http.routers.tooljet-http.entrypoints=web"
            - "traefik.http.routers.tooljet-http.middlewares=https-redirect"
            - "traefik.http.routers.tooljet-http.service=tooljet"
            - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
            - "traefik.http.middlewares.https-redirect.redirectscheme.permanent=true"
            - "traefik.http.services.tooljet.loadbalancer.server.port=80"

    postgres:
        container_name: ${PG_HOST}
        image: postgres:16
        restart: always
        volumes:
            - postgres:/var/lib/postgresql/data
        env_file: .env
        environment:
            - POSTGRES_USER=${PG_USER}
            - POSTGRES_PASSWORD=${PG_PASS}
        networks:
            - default

networks:
    default:
    caddy:
        external: true

volumes:
    postgres:
        driver: local
        driver_opts:
            o: bind
            type: none
            device: ${PWD}/postgres_data
    certs:
    logs:
    fallbackcerts:

.env

# Create .env from this example file and replace values for the environment.
# The application expects a separate .env.test for test environment configuration
# Get detailed information about each variable here: https://docs.tooljet.com/docs/setup/env-vars

TOOLJET_HOST=https://tooljet.handtrixxx.com
LOCKBOX_MASTER_KEY=
SECRET_KEY_BASE=

# DATABASE CONFIG
ORM_LOGGING=all
PG_DB=tooljet_production
PG_USER=postgres
PG_HOST=postgresql
PG_PASS=

# The above postgres values is set to its default state. If necessary, kindly modify it according to your personal preference.

# TOOLJET DATABASE
TOOLJET_DB=tooljet_db
TOOLJET_DB_USER=postgres
TOOLJET_DB_HOST=postgresql
TOOLJET_DB_PASS=

PGRST_DB_URI=postgres://postgres:TfNNf9qb5ScO4MZf@postgresql/tooljet_db
PGRST_HOST=localhost:3002
PGRST_JWT_SECRET=
PGRST_SERVER_PORT=3002
PGRST_DB_PRE_CONFIG=postgrest.pre_config


# Checks every 24 hours to see if a new version of ToolJet is available
# (Enabled by default. Set false to disable)
CHECK_FOR_UPDATES=true

# Checks every 24 hours to update app telemetry data to ToolJet hub.
# (Telemetry is enabled by default. Set value to true to disable.)
# DISABLE_TOOLJET_TELEMETRY=false

GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

# EMAIL CONFIGURATION
DEFAULT_FROM_EMAIL=hello@tooljet.io
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_DOMAIN=
SMTP_PORT=

# DISABLE USER SIGNUPS (true or false). only applicable if Multi-Workspace feature is enabled
DISABLE_SIGNUPS=


# OBSERVABILITY
APM_VENDOR=
SENTRY_DNS=
SENTRY_DEBUG=

# FEATURE TOGGLE
COMMENT_FEATURE_ENABLE=
ENABLE_MULTIPLAYER_EDITING=true
ENABLE_MARKETPLACE_FEATURE=true


# SSO (Applicable only for Multi-Workspace)
SSO_GOOGLE_OAUTH2_CLIENT_ID=
SSO_GIT_OAUTH2_CLIENT_ID=
SSO_GIT_OAUTH2_CLIENT_SECRET=
SSO_GIT_OAUTH2_HOST=
SSO_ACCEPTED_DOMAINS=
SSO_DISABLE_SIGNUPS=

#ONBOARDING
ENABLE_ONBOARDING_QUESTIONS_FOR_ALL_SIGN_UPS=

#session expiry in minutes
USER_SESSION_EXPIRY=2880

#TELEMETRY
DEPLOYMENT_PLATFORM=docker

# Workflow scheduling configuration
# Worker Mode
# Set to 'true' to enable job processing
# Set to 'false' or unset for HTTP-only mode (scaled deployments)
WORKER=true

# Workflow Processor Concurrency (optional)
# Number of workflow jobs processed concurrently per worker
# Default: 5
TOOLJET_WORKFLOW_CONCURRENCY=5

# Workflow Execution Timeout (optional)
# Maximum time (in seconds) for a workflow to execute
# Default: 60 seconds
WORKFLOW_TIMEOUT_SECONDS=60

Baserow

Baserow lässt sich ebenfalls sehr einfach einrichten.

Nach dem ersten Start werden wir von einem Assistenten begrüßt, über den wir unseren ersten User einrichten. Außerdem erstellt der Assistent eine Beispielapplikation anhand typischer Szenarien die wie auswählen dürfen.

Das Ganze lässt sich irgendwann überspringen und der Startbildschirm den wir sehen, sieht dann so aus:

Die Details zur Konfiguration hier im Unterkapitel Setup, im Kapitel Use Cases gucken wir uns das Tool dann genauer an.

Setup

compose.yml

Das Unterverzeichnis “data” sollte man zuvor erstellen.

services:
    baserow:
        container_name: baserow
        image: baserow/baserow:2.1.6
        environment:
            BASEROW_PUBLIC_URL: "https://baserow.handtrixxx.com"
        #ports:
        #  - "80:80"
        #  - "443:443"
        volumes:
            - ./data:/baserow/data
        networks:
            - caddy
        labels:
            - "traefik.enable=true"
            - "traefik.docker.network=caddy"
            - "traefik.http.routers.baserow.rule=Host(`baserow.handtrixxx.com`)"
            - "traefik.http.routers.baserow.entrypoints=websecure"
            - "traefik.http.routers.baserow.tls.certresolver=letsencrypt"
            - "traefik.http.routers.baserow.service=baserow"
            - "traefik.http.routers.baserow-http.rule=Host(`baserow.handtrixxx.com`)"
            - "traefik.http.routers.baserow-http.entrypoints=web"
            - "traefik.http.routers.baserow-http.middlewares=https-redirect"
            - "traefik.http.routers.baserow-http.service=baserow"
            - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
            - "traefik.http.middlewares.https-redirect.redirectscheme.permanent=true"
            - "traefik.http.services.baserow.loadbalancer.server.port=80"
networks:
    caddy:
        external: true

Budibase

Budibase ist etwas komplizierter, aber ebenso machbar.

Nach dem ersten Start werden wir vom Login Screen begrüßt, wo wir uns mit den in der .env Datei spezifizierten User anmelden.

Kurz danach begrüßt uns die modern wirkende Startoberfläche des Tools:

Die Details zur Konfiguration hier im Unterkapitel Setup, im Kapitel Use Cases gucken wir uns das Tool dann genauer an.

Setup

compose.yml

Die Labels sind nur erforderlich, wenn man Traefik nutzen will.

services:
    app-service:
        restart: unless-stopped
        image: budibase/apps:latest
        container_name: bbapps
        networks:
            - default
        environment:
            SELF_HOSTED: 1
            COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984
            WORKER_URL: http://worker-service:4003
            MINIO_URL: http://minio-service:9000
            MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
            MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
            INTERNAL_API_KEY: ${INTERNAL_API_KEY}
            BUDIBASE_ENVIRONMENT: ${BUDIBASE_ENVIRONMENT}
            PORT: 4002
            API_ENCRYPTION_KEY: ${API_ENCRYPTION_KEY}
            JWT_SECRET: ${JWT_SECRET}
            LOG_LEVEL: info
            ENABLE_ANALYTICS: "true"
            REDIS_URL: redis-service:6379
            REDIS_PASSWORD: ${REDIS_PASSWORD}
            REDIS_USERNAME: ${REDIS_USERNAME:-}
            LITELLM_URL: http://litellm-service:4000
            LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY}
            BB_ADMIN_USER_EMAIL: ${BB_ADMIN_USER_EMAIL}
            BB_ADMIN_USER_PASSWORD: ${BB_ADMIN_USER_PASSWORD}
            PLUGINS_DIR: ${PLUGINS_DIR}
            OFFLINE_MODE: ${OFFLINE_MODE:-}
        depends_on:
            - worker-service
            - redis-service
            - litellm-service
    #    volumes:
    #      - /some/path/to/plugins:/plugins

    worker-service:
        restart: unless-stopped
        image: budibase/worker
        container_name: bbworker
        networks:
            - default
        environment:
            SELF_HOSTED: 1
            PORT: 4003
            CLUSTER_PORT: ${MAIN_PORT}
            API_ENCRYPTION_KEY: ${API_ENCRYPTION_KEY}
            JWT_SECRET: ${JWT_SECRET}
            MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
            MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
            MINIO_URL: http://minio-service:9000
            APPS_URL: http://app-service:4002
            COUCH_DB_USERNAME: ${COUCH_DB_USER}
            COUCH_DB_PASSWORD: ${COUCH_DB_PASSWORD}
            COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984
            INTERNAL_API_KEY: ${INTERNAL_API_KEY}
            REDIS_URL: redis-service:6379
            REDIS_PASSWORD: ${REDIS_PASSWORD}
            REDIS_USERNAME: ${REDIS_USERNAME:-}
            LITELLM_URL: http://litellm-service:4000
            LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY}
            OFFLINE_MODE: ${OFFLINE_MODE:-}
        depends_on:
            - redis-service
            - minio-service
            - litellm-service

    minio-service:
        restart: unless-stopped
        image: minio/minio
        networks:
            - default
        volumes:
            - ./minio_data:/data
        environment:
            MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
            MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
            MINIO_BROWSER: "off"
        command: server /data --console-address ":9001"
        healthcheck:
            test: "timeout 5s bash -c ':> /dev/tcp/127.0.0.1/9000' || exit 1"
            interval: 30s
            timeout: 20s
            retries: 3

    proxy-service:
        restart: unless-stopped
        #ports:
        #    - "${MAIN_PORT}:10000"
        container_name: bbproxy
        image: budibase/proxy
        networks:
            - default
            - caddy
        environment:
            - PROXY_RATE_LIMIT_WEBHOOKS_PER_SECOND=10
            - PROXY_RATE_LIMIT_API_PER_SECOND=50
            - APPS_UPSTREAM_URL=http://app-service:4002
            - WORKER_UPSTREAM_URL=http://worker-service:4003
            - MINIO_UPSTREAM_URL=http://minio-service:9000
            - COUCHDB_UPSTREAM_URL=http://couchdb-service:5984
            - RESOLVER=127.0.0.11
        depends_on:
            - minio-service
            - worker-service
            - app-service
            - couchdb-service
        labels:
            - "traefik.enable=true"
            - "traefik.docker.network=caddy"
            - "traefik.http.routers.buddy.rule=Host(`buddy.handtrixxx.com`)"
            - "traefik.http.routers.buddy.entrypoints=websecure"
            - "traefik.http.routers.buddy.tls.certresolver=letsencrypt"
            - "traefik.http.routers.buddy.service=buddy"
            - "traefik.http.routers.buddy-http.rule=Host(`buddy.handtrixxx.com`)"
            - "traefik.http.routers.buddy-http.entrypoints=web"
            - "traefik.http.routers.buddy-http.middlewares=https-redirect"
            - "traefik.http.routers.buddy-http.service=buddy"
            - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
            - "traefik.http.middlewares.https-redirect.redirectscheme.permanent=true"
            - "traefik.http.services.buddy.loadbalancer.server.port=10000"
    couchdb-service:
        restart: unless-stopped
        image: budibase/database:2.1.0
        networks:
            - default
        environment:
            - COUCHDB_PASSWORD=${COUCH_DB_PASSWORD}
            - COUCHDB_USER=${COUCH_DB_USER}
            - TARGETBUILD=docker-compose
            - DATA_DIR=/data
        volumes:
            - ./couchdb3_data:/data

    redis-service:
        restart: unless-stopped
        image: redis
        networks:
            - default
        command: redis-server --requirepass "${REDIS_PASSWORD}"
        volumes:
            - ./redis_data:/data

    litellm-service:
        restart: unless-stopped
        image: docker.litellm.ai/berriai/litellm:1.80.15-stable.1
        #ports:
        #    - "${LITELLM_PORT:-4000}:4000"
        volumes:
            - ./litellm_config.yaml:/app/config.yaml
        environment:
            DATABASE_URL: "postgresql://${LITELLM_DB_USER}:${LITELLM_DB_PASSWORD}@litellm-db:5432/${LITELLM_DB_NAME}"
            STORE_MODEL_IN_DB: "True"
            LITELLM_REASONING_AUTO_SUMMARY: "true"
            LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY}
            LITELLM_SALT_KEY: ${LITELLM_SALT_KEY}
        command: ["--config", "/app/config.yaml"]
        depends_on:
            - litellm-db
        networks:
            - default
        healthcheck:
            test:
                [
                    "CMD-SHELL",
                    "wget --no-verbose --tries=1 http://localhost:4000/health/liveliness || exit 1",
                ]
            interval: 30s
            timeout: 10s
            retries: 3
            start_period: 40s

    litellm-db:
        restart: unless-stopped
        image: postgres:16
        environment:
            POSTGRES_DB: ${LITELLM_DB_NAME}
            POSTGRES_USER: ${LITELLM_DB_USER}
            POSTGRES_PASSWORD: ${LITELLM_DB_PASSWORD}
        volumes:
            - ./litellm_data:/var/lib/postgresql/data
        networks:
            - default
        healthcheck:
            test:
                [
                    "CMD-SHELL",
                    "pg_isready -d ${LITELLM_DB_NAME} -U ${LITELLM_DB_USER}",
                ]
            interval: 1s
            timeout: 5s
            retries: 10
networks:
    caddy:
        external: true

.env

auch wenn der “REDIS_USERNAME” sich setzen lässt, fährt die Anwendung dann nicht ohne weiteres Zutun hoch. Deshalb diesen zunächst als Kommentar stehen lassen.

# Use the main port in the builder for your self hosting URL, e.g. localhost:10000
MAIN_PORT=10000

# This section contains all secrets pertaining to the system
# These should be updated
# #openssl rand -hex 32

API_ENCRYPTION_KEY=
JWT_SECRET=
MINIO_ACCESS_KEY=
MINIO_SECRET_KEY=
COUCH_DB_PASSWORD=
COUCH_DB_USER=
REDIS_PASSWORD=
#REDIS_USERNAME=budiredis
INTERNAL_API_KEY=
LITELLM_MASTER_KEY=
LITELLM_SALT_KEY=
# This section contains variables that do not need to be altered under normal circumstances
APP_PORT=4002
WORKER_PORT=4003
MINIO_PORT=4004
COUCH_DB_PORT=4005
COUCH_DB_SQS_PORT=4006
REDIS_PORT=6379
BUDIBASE_ENVIRONMENT=PRODUCTION
SQL_MAX_ROWS=
LITELLM_PORT=4000
LITELLM_DB_NAME=litellm
LITELLM_DB_USER=llmproxy
LITELLM_DB_PASSWORD=

# An admin user can be automatically created initially if these are set
BB_ADMIN_USER_EMAIL=
BB_ADMIN_USER_PASSWORD=

# A path that is watched for plugin bundles. Any bundles found are imported automatically/
PLUGINS_DIR=
ROLLING_LOG_MAX_SIZE=

litellm_config.yaml

Ohne diese Datei fährt Budibase nicht hoch, der Inhalt muss aber nur semantisch korrekt sein. Also lassen sich die folgenden Beispielwerte einfach 1:1 übernehmen.

model_list:
    - model_name: azure-gpt-4o
      litellm_params:
          model: azure/<your-azure-model-deployment>
          api_base: os.environ/AZURE_API_BASE # runs os.getenv("AZURE_API_BASE")
          api_key: os.environ/AZURE_API_KEY # runs os.getenv("AZURE_API_KEY")
          api_version: "2025-01-01-preview"

Use Case 1

Wir bauen eine Web-App die Daten aus einer API konsumiert und in funktionsgerechten Tabellen darstellt.

Als Quelle nehmen wir die Stromberg-API von https://stromberg-api.de/ .

Über einen Get Request von https://stromberg-api.de/api/quotes bekommen wir eine JSON Antwort mit folgendem Schema.

Diese Antwort wollen wir dann im Tool als eine hübsche Tabelle anzeigen, in der man die Felder sortieren und filtern kann.

Tooljet

Als erstes erstellen wir eine neue App mit einem beliebigen Namen, und dann können wir schon direkt eine sogenannte “Query” erstellen, wo uns “Rest-API” als Quelle zur Verfügung steht.

Das war auch schon beinahe das schwierigste. Über die Komponentenbibliothek rechts fügen wir unserer App eine Tabelle hinzu und wähle für diese den zuvor definierten Endpunkt.

Dann kann man noch alles mögliche einstellen, und die “App” dann entweder intern oder im Internet frei zugänglich veröffentlichen.

Das ist Klasse, der Use Case wurde zu 100% in 7 Minuten erfüllt.

Budibase

Nach der positiven Erfahrung mit Tooljet nun direkt weiter mit Budibase.

Das erste was auffällt sind die allgegenwärtigen Erinnerungen und Aufforderungen auf einen anderen, kostenpflichtigen, Plan zu wechseln. Nicht schön, also weniger eine Community Projekt als mehr ein Unternehmen dahinter.

Um eine API-Quelle hinzuzufügen, die nicht im (aber beachtlich großen) Standardkatalog hinzuzufügen wählt man im Dialog “Create custom”.

Danach geht es aber dann genauso schnell wie bei Tooljet.

Ebenso sehr gut, wenn es etwas durchschaubarer wäre, welche Funktionen einem in der Community Edition nicht zur Verfügung stehen bzw. diese erst gar nicht angezeigt würden, wären es auch 100%. So eher 90% wegen des schlechten Bauchgefühls.

Appsmith

Auch mit Appsmith lässt sich unser Use Case in wenigen Minuten erfüllen. Das Ergebnis liegt irgendwo zwischen den sehr positiven Eindrücken von Budibase und Tooljet.

Einerseits sieht die UI etwas “altbackener” aus und die Filter Funktion habe ich auf Anhieb nicht gefunden, dafür zeigt die Appsmith Tabelle die Inhalte einer Spalte an auch wenn es sich um Objekt handelt.

Deshalb in Total eine 95% Bewertung.

Nocobase

Die erste Überraschung mit Nocobase. Nach der Standardinstallation lässt sich zunächst überhaupt keine externe Datenquelle definieren. Und auch nach dem lesen der Dokumentation bleibt das Ergebnis ernüchternd. Denn zur API Data Source steht geschrieben:

This is a commercial plugin. For detailed activation instructions, please refer to: Commercial Plugin Activation Guide

Damit hat sich dieser Use Case im Rahmen unseres Tests für uns erledigt.

Dadurch eine Bewertung von 0%.

Baserow

Ähnlich geht es bei Baserow weiter. Hier scheint es sogar so zu sein, dass die Verwendung eine externen Datenquelle gar nicht vorgesehen ist. D.h. es handelt sich eigentlich um eine Datenbankmanagementsystem mit einer GUI für Applikationen.

Deshalb auch hier für diesen Use Case eine Bewertung von 0%.

Zusammenfassung der Bewertung

  • Tooljet: 100%
  • Budibase: 90%
  • Appsmith: 95%
  • Nocobase: 0%
  • Baserow: 0%

Damit ist der Sieger mit ganz knappen Verfolgern hier Tooljet.

Use Case 2

Wir importieren Tabellen aus Excel Dateien und wollen diese schick darstellen.

Als Basis nehmen wir einen Excel Export der zuvor über die API importierte Tabelle.

Budibase

Ein direkter Excel Import ist nicht möglich, es funktionieren .csv und .json.

Das heißt dass wir unsere Excel Datei auf einem Client als erstes in das .csv Format bringen müssen.

Nun haben wir zwei Optionen:

  1. Wir legen eine neue Tabelle an, definieren Die Spalten und deren Datentypen oder aber
  2. Wir legen eine neue Tabelle an und wählen während des Anlegens die .csv Datei als Importquelle aus. Hier versucht Budibase die Spalten und deren Inhalt automatisch zu erkennen.

Da Option 2. Arbeit erspart habe ich diese getestet und das hat erstaunlich gut funktioniert.

Anschließend können wir diese Tabelle dann als Datenquelle analog zu Use Case 1 für eine Darstellung der Daten als Tabelle verwenden.

Zielerreichung des Uses Cases: 100%.

Nocobase

Vermutlich bin ich einfach zu blöd oder habe den Zweck von Nocobase einfach nicht verstanden. Jedenfalls war ich nicht in der Lage meine Daten aus der Excel Datei zu importieren, egal über welche Umwege.

Erfüllung des Use Cases: 0%.

Baserow

Für einen Import in Baserow können wir die Daten entweder per Copy & Paste kopieren oder aber sie in eine .csv Datei umwandeln und diese dann auswählen

Der Import selbst sah fehlerfrei aus.

Das Ergebnis war etwas umständlicher zu erreichen uns sah ohne weitere Konfiguration erst mal ein wenig altbacken aus.

Nichts desto trotz konnte der Use Case in wenigen Minuten erfüllt werden, so dass ich zu einer Gesamtwertung von 90% komme.

Appsmith

Appsmith zeigt bereits im Standard sehr verbindungsfreudig, scheint aber nicht dafür gemacht zu sein, Daten über dessen GUI zu importieren oder direkt neue Tabellen über die GUI zu erstellen. SQL Statements lassen sich ausführen, aber das war nicht das Ziel des Use Cases.

Weil es zumindest theoretisch mit etwas Mehrarbeit möglich wäre trotzdem noch eine Wertung von 20% Zielleereichung.

Tooljet

In Tooljet funktioniert der Massenimport über einen doppelten Umweg, aber zuverlässig.

Man muss zunächst in einer verknüpften Datenbank freier Wahl die Kopfzeilen/Datenfelder erstellen und dabei auch deren Datentypen festlegen.

Dann kann man die zuvor händisch in eine .csv Datei umgewandelte Excel Datei in diese Tabelle importieren.

Update: Ich habe jetzt erst gesehen, dass der User alternativ auch direkt eine Excel Datei verarbeiten kann. Damit erfüllt Tooljet nun 100% der kriterien.

Zusammenfassung der Bewertung

  • Baserow: 90%
  • Budibase: 100%
  • Appsmith: 20%
  • Nocobase: 0%
  • Tooljet: 100%

Ergebnis

RankToolBewertung
1.Budibase100%
1.Tooljet100%
3.Appsmith58%
4.Baserow45%
5.Nocobase0%

Bezogen auf meine beiden Use Cases teilen sich Budibase und Tooljet den ersten Platz. Da Tooljet mit etwas weniger Werbung auskommt ist dies vielleicht die erste Anlaufstelle für Tests in komplizierteren Szenarien zu empfehlen.

\