Build IFTTT
YESreplaces $2.99/mosaves $35.88/yrback to the verdict
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.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the service.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - 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 - 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 - 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 - 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.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DB_PATH | required | ./data/rules.db | Rules, events, runs and cursors. |
SECRETS_KEYsecret | required | generate-a-long-random-value | Encrypts the secret store. Kept outside the database; losing it loses the secrets deliberately. |
DEFAULT_MAX_RUNS_PER_HOUR | required | 30 | Default ceiling per rule. Exceeding it disables the rule rather than warning. |
WEBHOOK_BASE_URL | required | https://hooks.example.com | Where inbound endpoints live. Must be HTTPS. |
POLL_MIN_INTERVAL_SECONDS | required | 300 | Floor on polling frequency. Politeness to the sources and a limit on your own request volume. |
ALERT_WEBHOOKsecret | required | https://chat.example.com/hook | Where ceiling trips, failures and silent rules are reported. |
The build, in order
One trigger, one action, logged
A rule fires and you can see exactly what it sent and what came back.
Trigger and action as data, so a rule is inspectable rather than code.
Files
src/rules.jsEnough to debug, redacted at the boundary.
Files
src/log.jsA logging function that cannot emit a secret value, rather than discipline.
Files
src/redact.js
done when · tick each as it passeswatch 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.
Exactly once, and a ceiling
One event fires one action, and a runaway rule stops itself.
Unique on rule and key, in the database. Insert failure means duplicate.
Files
src/events.jsmigrations/Not a warning. A loop with side effects is the case this exists for.
Files
src/limits.jsA loop and a concurrent double poll. Untested safety is not safety.
Files
test/idempotency.test.js
done when · tick each as it passeswatch 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.
Polling politely with cursors
A polled source is checked without refetching everything and without missing items.
After a successful batch, not before. A cursor advanced on failure loses events.
Files
src/poll.jsCheaper for you and politer to the source.
Files
src/http.jsIf a poll returns a full page, there may be more. Truncating loses events silently.
Files
src/poll.js
done when · tick each as it passeswatch 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.
Inbound webhooks
A service can push to you, and a replayed delivery does not fire twice.
Queue and return. Slow processing inside the request causes redelivery.
Files
src/webhook.jsAnd where not, rely on the unguessable path and say so in the documentation.
Files
src/webhook.jsSo a redelivery deduplicates naturally.
Files
src/events.js
done when · tick each as it passeswatch 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.
Secrets outside the rules
A rule can be exported and shared without leaking a token.
Configs never contain values. Grep an export to confirm.
Files
src/secrets.jsList what is needed. A rule that fails with a service authorisation error is hard to diagnose.
Files
src/import.jsWith 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 passeswatch 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.
Running it continuouslyproduct builder
Rules run without supervision and you find out when one stops.
Restart safe. A cursor lost on restart replays or skips, and both are bad.
Files
src/service.jsExpected frequency per rule. Silence is the failure you will otherwise miss.
Files
src/health.jsRules, cursors and secrets. Without the key the secrets are gone, which is deliberate.
Files
scripts/backup.shREADME.md
done when · tick each as it passeswatch out- A rule that silently stops firing is indistinguishable from a rule whose trigger simply has not occurred, and you notice weeks later when something did not happen. Record an expected frequency per rule and alert when it is not met, since silence is the failure mode here.
That is the whole plan for IFTTT. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- The consumer integration catalogue.
- Smart home integrations.
- Mobile triggers from sensors and location.
- Anyone maintaining a connector when a service changes.
- consumer integration catalog
- smart-home integrations
- mobile applets
- easy UI
- maintenance when APIs change
- A filter step between trigger and action, which removes most of the need for more rules
- A dry run mode showing what a rule would do without doing it
- Templating action payloads from trigger data, which is where rules become genuinely useful
Need the files? The project pack on the verdict page hands your agent the whole brief · more automation.