Build IFTTT

YESreplaces $2.99/mosaves $35.88/yrback to the verdict

0%0 of 20 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

Rules connecting a trigger to an action: polled sources with change detection or inbound webhooks, an event key that makes each event fire exactly once, a per-rule rate ceiling that stops a runaway, a run log showing what happened, and secrets that live outside the rule definitions.

estimated effort weekendthe files for this build are in the project pack

RuntimeNode 22 with SQLiteTriggersScheduled polls with change detection, plus inbound webhooksIdempotencyAn event key per trigger, unique in the databaseActionsOutbound requests with retries and a per-rule ceilingSecretsStored outside rule definitions, referenced by name

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the service.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. have ready5 to 10 US dollars a month, or free on hardware you own

    Why Automations that only run while your laptop is open miss events and then fire a burst, which is worse than not running.

    Get it A small virtual server or a machine at home that stays on. This workload is tiny.

    Verify The service runs on a schedule and survives a reboot

  3. have readyroughly 10 to 15 US dollars a year for a domain

    Why Phase 4 needs one, and most services will not deliver to plain HTTP.

    Get it A domain pointed at your server with automatic certificates, or a tunnel for development.

    Verify A test delivery reaches your endpoint over HTTPS

  4. API keyfree for most personal API access

    Why One trigger source and one action target, both real. A test harness will not have the rate limits, pagination and redelivery behaviour that shape this build.

    Get it API keys or tokens for two services you actually use, scoped as narrowly as they allow.

    Verify A rule polls one and acts on the other successfully

  5. decidefree

    Why Phase 2's ceiling exists because a loop with external side effects is the expensive failure, and knowing which of your rules could form one determines how tight the ceiling should be.

    Get it Before enabling any rule, write down whether its action could cause its own trigger, directly or through another rule.

    Verify Each rule has a loop assessment recorded

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- rules(id, name, enabled, trigger_kind, trigger_config_json, action_kind, action_config_json, max_runs_per_hour)
- events(id, rule_id, event_key, payload_json, observed_at, state) · unique on rule and event key, which is the idempotency
- runs(id, event_id, started_at, finished_at, state, attempts, request_summary, response_summary, error)
- secrets(name, value_encrypted) · referenced from configs by name, never inlined
- cursors(rule_id, value, updated_at) · what a polled trigger has already seen
- The unique constraint on rule and event key is what makes exactly-once real rather than intended.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DB_PATHrequired./data/rules.dbRules, events, runs and cursors.
SECRETS_KEYsecretrequiredgenerate-a-long-random-valueEncrypts the secret store. Kept outside the database; losing it loses the secrets deliberately.
DEFAULT_MAX_RUNS_PER_HOURrequired30Default ceiling per rule. Exceeding it disables the rule rather than warning.
WEBHOOK_BASE_URLrequiredhttps://hooks.example.comWhere inbound endpoints live. Must be HTTPS.
POLL_MIN_INTERVAL_SECONDSrequired300Floor on polling frequency. Politeness to the sources and a limit on your own request volume.
ALERT_WEBHOOKsecretrequiredhttps://chat.example.com/hookWhere ceiling trips, failures and silent rules are reported.

The build, in order

  1. One trigger, one action, logged

    A rule fires and you can see exactly what it sent and what came back.

    1. Trigger and action as data, so a rule is inspectable rather than code.

      Files src/rules.js

    2. Enough to debug, redacted at the boundary.

      Files src/log.js

    3. A logging function that cannot emit a secret value, rather than discipline.

      Files src/redact.js

    done when · tick each as it passes
    watch out
    • Logging the full request including headers writes your tokens into a file you will later share while debugging. Redact secret values at the logging boundary rather than remembering not to log them, since the one you forget is the one that leaks.
  2. Exactly once, and a ceiling

    One event fires one action, and a runaway rule stops itself.

    1. Unique on rule and key, in the database. Insert failure means duplicate.

      Files src/events.jsmigrations/

    2. Not a warning. A loop with side effects is the case this exists for.

      Files src/limits.js

    3. A loop and a concurrent double poll. Untested safety is not safety.

      Files test/idempotency.test.js

    done when · tick each as it passes
    watch out
    • Checking for a duplicate in application code before inserting races with a concurrent poll, and two overlapping runs both pass the check. Put the constraint in the database and treat the insert failure as the duplicate signal.
    • A rate ceiling that only logs will not stop a loop. It must disable the rule, because a loop producing external side effects is exactly the case where you are not watching.
  3. Polling politely with cursors

    A polled source is checked without refetching everything and without missing items.

    1. After a successful batch, not before. A cursor advanced on failure loses events.

      Files src/poll.js

    2. Cheaper for you and politer to the source.

      Files src/http.js

    3. If a poll returns a full page, there may be more. Truncating loses events silently.

      Files src/poll.js

    done when · tick each as it passes
    watch out
    • Polling by fetching the latest twenty items and comparing against what you have seen works until more than twenty things happen between polls, and then you silently miss events. Use a cursor the source understands where one exists, and where it does not, poll frequently enough that the window cannot overflow and say so.
  4. Inbound webhooks

    A service can push to you, and a replayed delivery does not fire twice.

    1. Queue and return. Slow processing inside the request causes redelivery.

      Files src/webhook.js

    2. And where not, rely on the unguessable path and say so in the documentation.

      Files src/webhook.js

    3. So a redelivery deduplicates naturally.

      Files src/events.js

    done when · tick each as it passes
    watch out
    • Processing synchronously inside the webhook request means a slow action causes the source to time out and redeliver, which produces exactly the duplicate you were avoiding. Acknowledge immediately, queue the work, and let the idempotency handle the redelivery that will happen anyway.
  5. Secrets outside the rules

    A rule can be exported and shared without leaking a token.

    1. Configs never contain values. Grep an export to confirm.

      Files src/secrets.js

    2. List what is needed. A rule that fails with a service authorisation error is hard to diagnose.

      Files src/import.js

    3. With the key outside the database. Losing it loses the secrets, which is the right failure.

      Files src/crypto.js

    done when · tick each as it passes
    watch out
    • A rule containing an inline token gets exported to share an automation and the token goes with it, usually into a chat message. Reference by name from the start, because retrofitting means auditing every rule anyone has already exported.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more automation.