[HOW TO] Build a Daily Tarot Card Flow with HomeyScript

Hi everyone,

I wanted to create a small morning routine that sends one reflective prompt through Homey and optionally changes a light scene based on the selected card.

The requirements were simple:

  • No paid API
  • No account or API key
  • One card per calendar day
  • The same result if the Flow is retried
  • Reusable tags for notifications, dashboards, and light scenes

Instead of using Math.random(), the script creates a stable index from the current date. This prevents a failed or manually repeated Flow from selecting a different card on the same day.

The source is Deckaura’s open 78-card tarot dataset and developer resources. The dataset is structured, downloadable, and includes upright meanings, reversed meanings, elements, suits, and source URLs.

This is intended as a light daily reflection or smart home experiment, not as a tool for making important decisions.

HomeyScript

Create a new HomeyScript and paste the following code:

const DATASET_URL =
  "https://huggingface.co/datasets/Blacik/deckaura-tarot-card-meanings/resolve/main/tarot_card_meanings.csv";

function parseCSVLine(line) {
  const cells = [];
  let current = "";
  let insideQuotes = false;

  for (let i = 0; i < line.length; i++) {
    const character = line[i];

    if (character === '"') {
      if (insideQuotes && line[i + 1] === '"') {
        current += '"';
        i++;
      } else {
        insideQuotes = !insideQuotes;
      }
    } else if (character === "," && !insideQuotes) {
      cells.push(current);
      current = "";
    } else {
      current += character;
    }
  }

  cells.push(current);
  return cells;
}

function createDateKey() {
  const now = new Date();

  return [
    now.getFullYear(),
    String(now.getMonth() + 1).padStart(2, "0"),
    String(now.getDate()).padStart(2, "0"),
  ].join("-");
}

function hashDate(value) {
  let hash = 2166136261;

  for (let i = 0; i < value.length; i++) {
    hash ^= value.charCodeAt(i);
    hash = Math.imul(hash, 16777619);
  }

  return hash >>> 0;
}

const response = await fetch(DATASET_URL);

if (!response.ok) {
  throw new Error(`Dataset request failed with status ${response.status}`);
}

const csv = await response.text();
const lines = csv.trim().split(/\r?\n/);
const headers = parseCSVLine(lines.shift()).map(value => value.trim());

const cards = lines
  .map(line => {
    const values = parseCSVLine(line);
    const card = {};

    headers.forEach((header, index) => {
      card[header] = values[index] ?? "";
    });

    return card;
  })
  .filter(card => card.card_name);

if (cards.length !== 78) {
  throw new Error(`Expected 78 cards but received ${cards.length}`);
}

const dateKey = createDateKey();
const cardIndex = hashDate(dateKey) % cards.length;
const card = cards[cardIndex];

const message = `${card.card_name}: ${card.upright_meaning}`;

await tag("Daily Card Name", card.card_name);
await tag("Daily Card Meaning", card.upright_meaning);
await tag("Daily Card Message", message);
await tag("Daily Card Element", card.element || "None");
await tag("Daily Card Guide", card.guide_url);

log(`Date: ${dateKey}`);
log(`Card: ${card.card_name}`);
log(`Element: ${card.element}`);
log(`Meaning: ${card.upright_meaning}`);

return true;

Run the script once manually. This creates the HomeyScript tags so they become available in the Flow editor.

Advanced Flow setup

My basic Flow looks like this:

When:
Time is 07:30

Then:
Run the Daily Tarot Card HomeyScript

Then:
Send a mobile or Timeline notification

For the notification text, select the Daily Card Message tag from the tag picker.

You can also use Daily Card Guide in a dashboard or notification if you want to open the longer reference page.

Optional light scene

The Daily Card Element tag can be used to select a decorative light color:

Fire  -> warm orange
Water -> blue
Air   -> soft white
Earth -> green

I keep this branch separate from security, presence, and essential lighting automations. If the dataset request fails, the script stops and existing household Flows remain unaffected.

Why use a deterministic daily selection?

A normal random choice produces a new result every time the script runs. That can be confusing when a Flow is retried after a notification or network failure.

Using the date as the seed provides:

  • One stable card for the entire day
  • Safe manual retries
  • Easier debugging
  • Predictable dashboard behavior
  • No additional storage variable

The same technique could be reused for daily quotes, meal suggestions, household tasks, educational facts, or rotating family activities.

Would you store the selected card in a Logic variable as well, or are the HomeyScript tags sufficient for your Flows and dashboards?