DEV Community

Bruce Du
Bruce Du

Posted on

A copyable prompt can be a product feature: building it into Prefate Tarot

I built Prefate Tarot because I wanted a simple place to draw cards when I was unsure what came next. Its name combines “predict” and “fate.” The current tool offers free card drawing, card meanings, and an optional prompt that people can take to an AI they already use.

The interesting engineering problem is that this last feature does not need a model call. It needs a faithful export of the state the user has already created.

I'm Bruce, the maker of Prefate. This is a small implementation case study, with a simplified example of the approach.

Preserve the draw as data

A reading has a question, a spread, ordered cards, and an orientation for each card. The exporter should not shuffle again or infer missing values. It should format the existing result.

The distinction matters for a three-card spread: “past, present, future” and “current relationship, influences, possible developments” both contain three cards, but the positions mean different things. Reusing the generic labels in a scenario-specific export would quietly change the reading.

A simplified version of the boundary looks like this:

type DrawnCard = {
  name: string;
  reversed: boolean;
};

type Reading = {
  question: string;
  spread: string;
  positions: string[];
  cards: DrawnCard[];
};

function exportReading(reading: Reading): string {
  if (
    reading.cards.length === 0 ||
    reading.cards.length !== reading.positions.length
  ) {
    throw new Error("Cards and positions must match");
  }

  const lines = reading.cards.map((card, index) =>
    `${index + 1}. ${reading.positions[index]}: ${card.name} ` +
    `(${card.reversed ? "reversed" : "upright"})`
  );

  return [
    `Question: ${reading.question.trim() || "[Add your question]"}`,
    `Spread: ${reading.spread}`,
    ...lines,
    "Please interpret this reading in the context of my question.",
  ].join("\n");
}
Enter fullscreen mode Exit fullscreen mode

The production implementation resolves card names, orientations, and spread labels through translations. A scenario can supply its own three position labels. Those same labels appear on the result and in the exported prompt.

Preview before copying

An immediate copy button was not the most useful interaction. A person might want to replace the question placeholder, remove identifying details, or add context before taking the reading elsewhere.

The button now opens an editable preview. Copying uses the current editor value, not a freshly regenerated template. That sounds small, but regenerating on copy would discard the user's edits.

The editor also has to cope with different lengths. A single-card reading is short; a Celtic Cross has ten positions, and a question can add several paragraphs. The textarea measures its content and adds roughly two spare lines, while the dialog caps its height against the viewport. Long prompts scroll inside the editor, leaving the copy action available.

Clipboard failure is a real state

The copy action awaits navigator.clipboard.writeText. Only a resolved call produces the success message. If copying fails, the editable text stays visible so the user can select it manually.

This feature does not send the reading to an AI service. The user chooses whether and where to paste it. The receiving service's account requirements and pricing remain separate from Prefate.

Measure the action without collecting the question

To understand whether the feature is useful, I track three separate events after analytics consent: opening the preview, a successful copy, and a failed copy.

The event properties are limited to coarse context such as locale, spread ID, card count, and source path. An allowlist excludes the question text and the specific drawn cards. I can see which entry pages lead to prompt use without putting private reading content in analytics.

Opening a preview and successfully copying are different actions. Keeping them separate also makes a clipboard problem visible instead of counting every button click as a successful export.

The product lesson

For a small tool, preparing clear context can be useful on its own. The work is in preserving the user's state, making the output editable, and giving them a reliable handoff.

You can try the free three-card reading or the career reading with scenario-specific positions. Card meanings are available in the tool; personal AI interpretation happens only if you take the prompt to another service.

Writing disclosure: this article was drafted by an AI agent on behalf of Bruce Du. The agent checked the technical details against the current Prefate code. It has not undergone a separate human edit. The code above is a simplified illustration.

Top comments (0)