@firstlovecenter/ai-chat 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to `@firstlovecenter/ai-chat` are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.9.1] — 2026-05-09
9
+
10
+ Lets a host mount multiple chat surfaces side-by-side without yanking users between shells.
11
+
12
+ ### Added
13
+
14
+ - **`AiChatProps.basePath`** (`string`, optional, default `'/chat'`) — URL prefix the chat surface is mounted at. Sidebar `<Link>` entries resolve to `${basePath}/${sessionId}`, `+ New chat` pushes `${basePath}?new`, and the open-session router push uses the same prefix. Both `AiChat` and `VercelChat` honour it.
15
+
16
+ ### Migration notes
17
+
18
+ - Pure addition — `basePath` defaults to `/chat`, so existing `/chat`-mounted surfaces work unchanged.
19
+ - Hosts that want a second surface (e.g. an admin AI page at `/admin/ai`) need to (a) pass `basePath="/admin/ai"`, (b) add a matching dynamic segment (`/admin/ai/[id]`) so reload/bookmark URLs resolve, and (c) wire a redirect-to-most-recent at the basePath that respects `?new`.
20
+ - **Tailwind v4 hosts**: the package ships no CSS, so its component classes need to be in your Tailwind content scan. Add `@source "../node_modules/@firstlovecenter/ai-chat";` to your `globals.css` (path relative to the CSS file). Without this, the in-chat sidebar's `absolute`/`translate-x-*`/`bg-sidebar` classes are stripped from the production bundle and the sidebar renders as a static flex column instead of an overlay.
21
+
8
22
  ## [0.9.0] — 2026-05-09
9
23
 
10
24
  Chat session and message identifiers are now short URL-safe UIDs (12 chars) instead of auto-incrementing BIGINTs. URLs like `/chat/V1StGXR8_Z5j` don't leak per-user chat counts and are unguessable, which matters as soon as a session URL is ever shared.
package/dist/ui/index.cjs CHANGED
@@ -678,7 +678,8 @@ function AiChat({
678
678
  userFirstName,
679
679
  scopeLabel,
680
680
  initialProvider,
681
- initialSessionId = null
681
+ initialSessionId = null,
682
+ basePath = "/chat"
682
683
  }) {
683
684
  const router = navigation.useRouter();
684
685
  const [sessions, setSessions] = React.useState([]);
@@ -768,16 +769,16 @@ function AiChat({
768
769
  }, []);
769
770
  const syncUrl = React.useCallback(
770
771
  (id) => {
771
- router.push(id == null ? "/chat" : `/chat/${id}`);
772
+ router.push(id == null ? basePath : `${basePath}/${id}`);
772
773
  },
773
- [router]
774
+ [router, basePath]
774
775
  );
775
776
  const newChat = React.useCallback(() => {
776
777
  setActiveSessionId(null);
777
778
  setAnswers([]);
778
779
  setQuestion("");
779
- router.push("/chat?new");
780
- }, [router]);
780
+ router.push(`${basePath}?new`);
781
+ }, [router, basePath]);
781
782
  const changeProvider = React.useCallback(
782
783
  async (next) => {
783
784
  if (next === provider || providerSaving) return;
@@ -1030,7 +1031,7 @@ function AiChat({
1030
1031
  /* @__PURE__ */ jsxRuntime.jsx(
1031
1032
  Link__default.default,
1032
1033
  {
1033
- href: `/chat/${s.id}`,
1034
+ href: `${basePath}/${s.id}`,
1034
1035
  onClick: () => setSidebarOpen(false),
1035
1036
  className: cn(
1036
1037
  "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm",
@@ -1513,7 +1514,8 @@ function VercelChat({
1513
1514
  userFirstName,
1514
1515
  scopeLabel,
1515
1516
  initialProvider,
1516
- initialSessionId = null
1517
+ initialSessionId = null,
1518
+ basePath = "/chat"
1517
1519
  }) {
1518
1520
  const router = navigation.useRouter();
1519
1521
  const [sessions, setSessions] = React.useState([]);
@@ -1744,9 +1746,9 @@ function VercelChat({
1744
1746
  }, [answers.length]);
1745
1747
  const syncUrl = React.useCallback(
1746
1748
  (id) => {
1747
- router.push(id == null ? "/chat" : `/chat/${id}`);
1749
+ router.push(id == null ? basePath : `${basePath}/${id}`);
1748
1750
  },
1749
- [router]
1751
+ [router, basePath]
1750
1752
  );
1751
1753
  const newChat = React.useCallback(() => {
1752
1754
  setActiveSessionId(null);
@@ -1756,8 +1758,8 @@ function VercelChat({
1756
1758
  setHydratedErrors({});
1757
1759
  setStartedAt({});
1758
1760
  setInput("");
1759
- router.push("/chat?new");
1760
- }, [setMessages, setInput, router]);
1761
+ router.push(`${basePath}?new`);
1762
+ }, [setMessages, setInput, router, basePath]);
1761
1763
  const changeProvider = React.useCallback(
1762
1764
  async (next) => {
1763
1765
  if (next === provider || providerSaving) return;
@@ -1987,7 +1989,7 @@ function VercelChat({
1987
1989
  /* @__PURE__ */ jsxRuntime.jsx(
1988
1990
  Link__default.default,
1989
1991
  {
1990
- href: `/chat/${s.id}`,
1992
+ href: `${basePath}/${s.id}`,
1991
1993
  onClick: () => setSidebarOpen(false),
1992
1994
  className: cn(
1993
1995
  "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm",