Skip to content

Getting started ​

Install ​

sh
npm install effect-prophet effect

Effect Prophet needs Node.js 22.19 or newer and is an ES module, so use import, not require. It also runs in browsers; see Browsers and bundlers.

Your first forecast ​

Copy this into a file called forecast.ts:

ts
import { Effect } from "effect";
import { fit, makeFutureTimestamps, predict, prophetFittingBackendLayer } from "effect-prophet";

// 1. Your history: one row per day, each with a timestamp and a value.
const history = Array.from({ length: 90 }, (_, day) => ({
  timestamp: new Date(Date.UTC(2025, 0, 1 + day)).toISOString(),
  value: 100 + day * 0.5 + 10 * Math.sin((2 * Math.PI * day) / 7),
}));

// 2. Describe the work: fit a model to the history, list the next seven days, then predict.
const program = Effect.gen(function* () {
  const model = yield* fit(history);
  const nextWeek = yield* makeFutureTimestamps(history, { periods: 7, includeHistory: false });

  return yield* predict(model, nextWeek);
});

// 3. Run it. The layer plugs in the forecasting engine.
const forecast = await Effect.runPromise(program.pipe(Effect.provide(prophetFittingBackendLayer)));

for (const row of forecast) {
  console.log(new Date(row.timestamp).toISOString().slice(0, 10), row.value.toFixed(1));
}

Run it:

sh
node forecast.ts

You should see a forecast for each of the next seven days:

txt
2025-04-01 137.2
2025-04-02 145.5
2025-04-03 153.8
2025-04-04 156.2
2025-04-05 151.3
2025-04-06 143.2
2025-04-07 138.3

The numbers rise and fall through the week because the model found the weekly pattern in the history on its own.

What just happened? ​

  1. History. Each row has a timestamp and a value. Timestamps are UTC strings in the exact format that Date.prototype.toISOString() produces.
  2. Fit, then predict. fit learns the trend and patterns from your history. makeFutureTimestamps lists the seven days after the history's last timestamp, and predict uses the fitted model to forecast them. You can also pass predict any dates you choose, in the future or the past.
  3. Run. Steps 1 and 2 only describe the work. Effect.runPromise runs it and gives you a normal Promise. prophetFittingBackendLayer supplies the forecasting engine that fit needs.

If steps 2 and 3 feel unfamiliar, read Effect in five minutes. It is short.

Fit and predict in one call ​

When you only need the forecast, forecast fits and predicts in one call:

ts
import { Effect } from "effect";
import { forecast, prophetFittingBackendLayer } from "effect-prophet";

const history = Array.from({ length: 90 }, (_, day) => ({
  timestamp: new Date(Date.UTC(2025, 0, 1 + day)).toISOString(),
  value: 100 + day * 0.5 + 10 * Math.sin((2 * Math.PI * day) / 7),
}));

const nextWeek = Array.from({ length: 7 }, (_, offset) =>
  new Date(Date.UTC(2025, 0, 91 + offset)).toISOString(),
);

// Fit the history and forecast next week in one call.
const rows = await Effect.runPromise(
  forecast(history, nextWeek).pipe(Effect.provide(prophetFittingBackendLayer)),
);

for (const row of rows) {
  console.log(new Date(row.timestamp).toISOString().slice(0, 10), row.value.toFixed(1));
}
txt
2025-04-01 137.2
2025-04-02 145.5
2025-04-03 153.8
2025-04-04 156.2
2025-04-05 151.3
2025-04-06 143.2
2025-04-07 138.3

The result is exactly what fit and then predict return, in the order of your dates. Model options go in an optional third argument, exactly as fit takes them:

ts
forecast(history, nextWeek, { growth: "flat" });

forecast returns only the forecast, not the model. To forecast again from the same model, or to save it, call fit and predict yourself. Like predict, it doesn't guess anything about the future: you list the dates, and any capacities, floors, regressors or conditions the model needs go on each row, as in this regressor example.

Next steps ​

Inspired by Prophet from Meta. Not affiliated with Meta.