Meet Frontfriend.Your brand. Your rules. Your agents, connected.Explore what’s new

Checkpoint

A conversation checkpoint that restores the thread from a saved turn.

Interactive preview

The shared preview uses React Base. The source below uses Reka UI. Each example runs with local data.

Installation

Complete project setup with vue/reka, then install these components:

pnpm exec frontfriend download message marker button bubble -f vue --primitive reka

Restore keeps the checkpoint message. Continue adds a new turn after it. The marker remains visible, and the status text announces the result. In an application, restore the matching application state as well as the messages.

Usage

Complete example

<script setup lang="ts">
import { ref } from "vue";
import { Message } from "@/components/ui/message";
import { MessageContent } from "@/components/ui/message";
import { Bubble } from "@/components/ui/bubble";
import { BubbleContent } from "@/components/ui/bubble";
import { Marker } from "@/components/ui/marker";
import { MarkerContent } from "@/components/ui/marker";
import { Button } from "@/components/ui/button";

const args = {
  "label": "Layout saved",
};
const messages = ref([
  { id: "user-1", role: "user", text: "Build the page layout." },
  {
    id: "assistant-1",
    role: "assistant",
    text: "The page layout is ready.",
  },
  {
    id: "user-2",
    role: "user",
    text: "Add a footer with the project links.",
  },
  {
    id: "assistant-2",
    role: "assistant",
    text: "I added the footer and its links.",
  },
]);
const status = ref("");
const continueContainer = ref<HTMLDivElement | null>(null);
function restore() {
  messages.value = messages.value.slice(0, 2);
  status.value = "Restored. Later turns removed.";
  continueContainer.value?.querySelector("button")?.focus();
}
function next() {
  messages.value.push(
    {
      id: crypto.randomUUID(),
      role: "user",
      text: "Continue from this layout.",
    },
    {
      id: crypto.randomUUID(),
      role: "assistant",
      text: "I will keep the saved layout and add the next change.",
    },
  );
  status.value = "Added a new exchange.";
}
</script>

<template>
  <div
    style="
      width: 100%;
      max-width: 560px;
      min-width: 0;
      margin-inline: auto;
      display: flex;
      flex-direction: column;
      gap: 20px;
      padding-block: 16px;
      font-size: var(--text-sm);
      line-height: 1.5;
    "
  >
    <template v-for="message in messages" :key="message.id"
      ><Message :align="message.role === 'user' ? 'end' : 'start'"
        ><MessageContent
          ><Bubble v-if="message.role === 'user'" align="end" variant="muted"
            ><BubbleContent>{{ message.text }}</BubbleContent></Bubble
          >
          <p v-else>{{ message.text }}</p></MessageContent
        ></Message
      >
      <Marker v-if="message.id === 'assistant-1'" variant="separator"
        ><MarkerContent
          ><span
            style="
              display: inline-flex;
              gap: 8px;
              align-items: center;
              flex-wrap: wrap;
            "
            >{{ args.label
            }}<Button
              v-if="messages.length > 2"
              size="xs"
              variant="outline"
              :aria-label="'Restore to ' + args.label"
              @click="restore"
              >Restore</Button
            ></span
          ></MarkerContent
        ></Marker
      >
    </template>
    <div ref="continueContainer">
      <Button variant="outline" size="sm" @click="next">Continue</Button>
    </div>
    <p
      role="status"
      style="
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
        border: 0;
      "
    >
      {{ status }}
    </p>
  </div>
</template>

Components and API

This composition has no separate component API. Use the APIs for its installed components.

ComponentTarget reference
message Reka UI API
marker Reka UI API
button Reka UI API
bubble Reka UI API