Audiences, multi-step campaigns, a scheduled sending engine, open tracking, and stop-on-reply. A lemlist clone where every moving part is an inspectable Windmill job.
Windmill concepts demonstrated
- Two raw apps — one for campaigns and sequences, one for contacts and audiences.
- Schedule — runs the sending engine every ten minutes.
- Flow with a parallel loop — sends each due email as its own retryable job.
- HTTP route — serves the open-tracking pixel.
- Email trigger — a reply stops that contact's sequence.
- Resource + variables — the SMTP account and the support address.
- Datatables — contacts, audiences, campaigns, steps, enrollments, events.
Domain model
- Contact — global pool, keyed by email.
- Audience (
list) — a named set of contacts; deleting one cascades membership, not contacts. - Campaign — an ordered sequence of steps (subject, body, delay), status
draft/active/paused. - Enrollment — one contact's progress through one campaign. Advances step by step, stops on reply or unsubscribe.
- Event — sends and opens.
Layout
Audiences lemlist_create_list / get_list / list_lists / delete_list
lemlist_add_contacts / add_to_list / add_existing_to_list / remove_member
Contacts lemlist_list_contacts
Campaigns lemlist_create_campaign / get_campaign / list_campaigns / delete_campaign
lemlist_save_steps / lemlist_set_status
Enrollment lemlist_enroll / lemlist_enroll_list / lemlist_stop_enrollment
Engine lemlist_query_due → lemlist_send_one (flow)
lemlist_process_due (single script, scheduled)
Tracking lemlist_track_open + lemlist_track_open.http_trigger.yaml
Replies lemlist_inbound_reply + lemlist_inbound_reply.email_trigger.yaml
Apps lemlist_dashboard__raw_app/ · lemlist_audiences__raw_app/
Going live
- Fill in
smtp.resource.yamlwith a real SMTP account. - Set the
f/lemlist/support_addressvariable. - Enable
lemlist_engine.schedule.yaml(or point the schedule atlemlist_send_flowfor the fan-out engine).
Try it locally
wmill script preview f/lemlist/lemlist_query_due -d '{}'
wmill flow preview f/lemlist/lemlist_send_flow -d '{"smtp":"$res:f/lemlist/smtp"}'