create-better-t-stack 2.38.1 → 2.39.0-canary.bae99c30

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/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { createBtsCli } from "./src-DlPots7G.js";
2
+ import { createBtsCli } from "./src-CHXGSisf.js";
3
3
 
4
4
  //#region src/cli.ts
5
5
  createBtsCli().run();
package/dist/index.d.ts CHANGED
@@ -261,7 +261,7 @@ declare const router: trpcServer.TRPCBuiltRouter<{
261
261
  }>>;
262
262
  declare function createBtsCli(): trpc_cli0.TrpcCli;
263
263
  /**
264
- * Initialize a new Better-T Stack project
264
+ * Initialize a new Better-T-Stack project
265
265
  *
266
266
  * @example CLI usage:
267
267
  * ```bash
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { builder, createBtsCli, docs, init, router, sponsors } from "./src-DlPots7G.js";
2
+ import { builder, createBtsCli, docs, init, router, sponsors } from "./src-CHXGSisf.js";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -107,6 +107,7 @@ const dependencyVersionMap = {
107
107
  "@ai-sdk/vue": "^2.0.9",
108
108
  "@ai-sdk/svelte": "^3.0.9",
109
109
  "@ai-sdk/react": "^2.0.9",
110
+ streamdown: "^1.1.6",
110
111
  "@orpc/server": "^1.8.4",
111
112
  "@orpc/client": "^1.8.4",
112
113
  "@orpc/tanstack-query": "^1.8.4",
@@ -502,49 +503,6 @@ function validateWorkersCompatibility(providedFlags, options, config) {
502
503
  if (providedFlags.has("database") && config.database === "mongodb" && config.runtime === "workers") exitWithError("MongoDB database is not compatible with Cloudflare Workers runtime. MongoDB requires Prisma or Mongoose ORM, but Workers runtime only supports Drizzle ORM. Please use a different database or runtime.");
503
504
  if (providedFlags.has("dbSetup") && options.dbSetup === "docker" && config.runtime === "workers") exitWithError("Docker setup (--db-setup docker) is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.");
504
505
  }
505
- function coerceBackendPresets(config) {
506
- if (config.backend === "convex") {
507
- config.database = "none";
508
- config.orm = "none";
509
- config.api = "none";
510
- config.runtime = "none";
511
- config.dbSetup = "none";
512
- config.examples = ["todo"];
513
- }
514
- if (config.backend === "none") {
515
- config.auth = "none";
516
- config.database = "none";
517
- config.orm = "none";
518
- config.api = "none";
519
- config.runtime = "none";
520
- config.dbSetup = "none";
521
- config.examples = [];
522
- }
523
- }
524
- function incompatibleFlagsForBackend(backend, providedFlags, options) {
525
- const list = [];
526
- if (backend === "convex") {
527
- if (providedFlags.has("auth") && options.auth && options.auth !== "none" && options.auth !== "clerk") list.push(`--auth ${options.auth}`);
528
- if (providedFlags.has("database") && options.database !== "none") list.push(`--database ${options.database}`);
529
- if (providedFlags.has("orm") && options.orm !== "none") list.push(`--orm ${options.orm}`);
530
- if (providedFlags.has("api") && options.api !== "none") list.push(`--api ${options.api}`);
531
- if (providedFlags.has("runtime") && options.runtime !== "none") list.push(`--runtime ${options.runtime}`);
532
- if (providedFlags.has("dbSetup") && options.dbSetup !== "none") list.push(`--db-setup ${options.dbSetup}`);
533
- }
534
- if (backend === "none") {
535
- if (providedFlags.has("auth") && options.auth && options.auth !== "none") list.push(`--auth ${options.auth}`);
536
- if (providedFlags.has("database") && options.database !== "none") list.push(`--database ${options.database}`);
537
- if (providedFlags.has("orm") && options.orm !== "none") list.push(`--orm ${options.orm}`);
538
- if (providedFlags.has("api") && options.api !== "none") list.push(`--api ${options.api}`);
539
- if (providedFlags.has("runtime") && options.runtime !== "none") list.push(`--runtime ${options.runtime}`);
540
- if (providedFlags.has("dbSetup") && options.dbSetup !== "none") list.push(`--db-setup ${options.dbSetup}`);
541
- if (providedFlags.has("examples") && options.examples) {
542
- const hasNonNoneExamples = options.examples.some((ex) => ex !== "none");
543
- if (hasNonNoneExamples) list.push("--examples");
544
- }
545
- }
546
- return list;
547
- }
548
506
  function validateApiFrontendCompatibility(api, frontends = []) {
549
507
  const includesNuxt = frontends.includes("nuxt");
550
508
  const includesSvelte = frontends.includes("svelte");
@@ -1389,7 +1347,7 @@ const getLatestCLIVersion = () => {
1389
1347
  */
1390
1348
  function isTelemetryEnabled() {
1391
1349
  const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
1392
- const BTS_TELEMETRY = "1";
1350
+ const BTS_TELEMETRY = "0";
1393
1351
  if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
1394
1352
  if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
1395
1353
  return true;
@@ -1397,8 +1355,8 @@ function isTelemetryEnabled() {
1397
1355
 
1398
1356
  //#endregion
1399
1357
  //#region src/utils/analytics.ts
1400
- const POSTHOG_API_KEY = "phc_8ZUxEwwfKMajJLvxz1daGd931dYbQrwKNficBmsdIrs";
1401
- const POSTHOG_HOST = "https://us.i.posthog.com";
1358
+ const POSTHOG_API_KEY = "random";
1359
+ const POSTHOG_HOST = "random";
1402
1360
  function generateSessionId() {
1403
1361
  const rand = Math.random().toString(36).slice(2);
1404
1362
  const now = Date.now().toString(36);
@@ -1751,14 +1709,9 @@ function validateBackendConstraints(config, providedFlags, options) {
1751
1709
  if (providedFlags.has("backend") && backend && backend !== "convex" && backend !== "none") {
1752
1710
  if (providedFlags.has("runtime") && options.runtime === "none") exitWithError("'--runtime none' is only supported with '--backend convex' or '--backend none'. Please choose 'bun', 'node', or remove the --runtime flag.");
1753
1711
  }
1754
- if (backend === "convex" || backend === "none") {
1755
- const incompatibleFlags = incompatibleFlagsForBackend(backend, providedFlags, options);
1756
- if (incompatibleFlags.length > 0) exitWithError(`The following flags are incompatible with '--backend ${backend}': ${incompatibleFlags.join(", ")}. Please remove them.`);
1757
- if (backend === "convex" && providedFlags.has("frontend") && options.frontend) {
1758
- const incompatibleFrontends = options.frontend.filter((f) => f === "solid");
1759
- if (incompatibleFrontends.length > 0) exitWithError(`The following frontends are not compatible with '--backend convex': ${incompatibleFrontends.join(", ")}. Please choose a different frontend or backend.`);
1760
- }
1761
- coerceBackendPresets(config);
1712
+ if (backend === "convex" && providedFlags.has("frontend") && options.frontend) {
1713
+ const incompatibleFrontends = options.frontend.filter((f) => f === "solid");
1714
+ if (incompatibleFrontends.length > 0) exitWithError(`The following frontends are not compatible with '--backend convex': ${incompatibleFrontends.join(", ")}. Please choose a different frontend or backend.`);
1762
1715
  }
1763
1716
  }
1764
1717
  function validateFrontendConstraints(config, providedFlags) {
@@ -1825,6 +1778,25 @@ function extractAndValidateProjectName(projectName, projectDirectory, throwOnErr
1825
1778
 
1826
1779
  //#endregion
1827
1780
  //#region src/validation.ts
1781
+ const CORE_STACK_FLAGS = new Set([
1782
+ "database",
1783
+ "orm",
1784
+ "backend",
1785
+ "runtime",
1786
+ "frontend",
1787
+ "addons",
1788
+ "examples",
1789
+ "auth",
1790
+ "dbSetup",
1791
+ "api",
1792
+ "webDeploy",
1793
+ "serverDeploy"
1794
+ ]);
1795
+ function validateYesFlagCombination(options, providedFlags) {
1796
+ if (!options.yes) return;
1797
+ const coreStackFlagsProvided = Array.from(providedFlags).filter((flag) => CORE_STACK_FLAGS.has(flag));
1798
+ if (coreStackFlagsProvided.length > 0) exitWithError(`Cannot combine --yes with core stack configuration flags: ${coreStackFlagsProvided.map((f) => `--${f}`).join(", ")}. The --yes flag uses default configuration. Remove these flags or use --yes without them.`);
1799
+ }
1828
1800
  function processAndValidateFlags(options, providedFlags, projectName) {
1829
1801
  if (options.yolo) {
1830
1802
  const cfg = processFlags(options, projectName);
@@ -1832,6 +1804,7 @@ function processAndValidateFlags(options, providedFlags, projectName) {
1832
1804
  if (validatedProjectName$1) cfg.projectName = validatedProjectName$1;
1833
1805
  return cfg;
1834
1806
  }
1807
+ validateYesFlagCombination(options, providedFlags);
1835
1808
  try {
1836
1809
  validateArrayOptions(options);
1837
1810
  } catch (error) {
@@ -1844,6 +1817,10 @@ function processAndValidateFlags(options, providedFlags, projectName) {
1844
1817
  return config;
1845
1818
  }
1846
1819
  function processProvidedFlagsWithoutValidation(options, projectName) {
1820
+ if (!options.yolo) {
1821
+ const providedFlags = getProvidedFlags(options);
1822
+ validateYesFlagCombination(options, providedFlags);
1823
+ }
1847
1824
  const config = processFlags(options, projectName);
1848
1825
  const validatedProjectName = extractAndValidateProjectName(projectName, options.projectDirectory, true);
1849
1826
  if (validatedProjectName) config.projectName = validatedProjectName;
@@ -2369,6 +2346,10 @@ async function setupExamplesTemplate(projectDir, context) {
2369
2346
  if (hasReactWeb) {
2370
2347
  const exampleWebSrc = path.join(exampleBaseDir, "web/react");
2371
2348
  if (await fs.pathExists(exampleWebSrc)) {
2349
+ if (example === "ai") {
2350
+ const exampleWebBaseSrc = path.join(exampleWebSrc, "base");
2351
+ if (await fs.pathExists(exampleWebBaseSrc)) await processAndCopyFiles("**/*", exampleWebBaseSrc, webAppDir, context, false);
2352
+ }
2372
2353
  const reactFramework = context.frontend.find((f) => [
2373
2354
  "next",
2374
2355
  "react-router",
@@ -2972,9 +2953,9 @@ async function addAddonsToProject(input) {
2972
2953
  try {
2973
2954
  const projectDir = input.projectDir || process.cwd();
2974
2955
  const isBetterTStack = await isBetterTStackProject(projectDir);
2975
- if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T Stack project. Please run this command from the root of a Better-T Stack project.");
2956
+ if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T-Stack project. Please run this command from the root of a Better-T-Stack project.");
2976
2957
  const detectedConfig = await detectProjectConfig(projectDir);
2977
- if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T Stack project.");
2958
+ if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T-Stack project.");
2978
2959
  const config = {
2979
2960
  projectName: detectedConfig.projectName || path.basename(projectDir),
2980
2961
  projectDir,
@@ -3742,9 +3723,9 @@ async function addDeploymentToProject(input) {
3742
3723
  try {
3743
3724
  const projectDir = input.projectDir || process.cwd();
3744
3725
  const isBetterTStack = await isBetterTStackProject(projectDir);
3745
- if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T Stack project. Please run this command from the root of a Better-T Stack project.");
3726
+ if (!isBetterTStack) exitWithError("This doesn't appear to be a Better-T-Stack project. Please run this command from the root of a Better-T-Stack project.");
3746
3727
  const detectedConfig = await detectProjectConfig(projectDir);
3747
- if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T Stack project.");
3728
+ if (!detectedConfig) exitWithError("Could not detect the project configuration. Please ensure this is a valid Better-T-Stack project.");
3748
3729
  if (input.webDeploy && detectedConfig.webDeploy === input.webDeploy) exitWithError(`${input.webDeploy} web deployment is already configured for this project.`);
3749
3730
  if (input.serverDeploy && detectedConfig.serverDeploy === input.serverDeploy) exitWithError(`${input.serverDeploy} server deployment is already configured for this project.`);
3750
3731
  const config = {
@@ -3854,7 +3835,7 @@ async function setupExamples(config) {
3854
3835
  const dependencies = ["ai"];
3855
3836
  if (hasNuxt) dependencies.push("@ai-sdk/vue");
3856
3837
  else if (hasSvelte) dependencies.push("@ai-sdk/svelte");
3857
- else if (hasReactWeb) dependencies.push("@ai-sdk/react");
3838
+ else if (hasReactWeb) dependencies.push("@ai-sdk/react", "streamdown");
3858
3839
  await addPackageDependency({
3859
3840
  dependencies,
3860
3841
  projectDir: webClientDir
@@ -5768,7 +5749,7 @@ async function displayPostInstallInstructions(config) {
5768
5749
  if (noOrmWarning) output += `\n${noOrmWarning.trim()}\n`;
5769
5750
  if (bunWebNativeWarning) output += `\n${bunWebNativeWarning.trim()}\n`;
5770
5751
  output += `\n${pc.bold("Update all dependencies:\n")}${pc.cyan(tazeCommand)}\n\n`;
5771
- output += `${pc.bold("Like Better-T Stack?")} Please consider giving us a star\n on GitHub:\n`;
5752
+ output += `${pc.bold("Like Better-T-Stack?")} Please consider giving us a star\n on GitHub:\n`;
5772
5753
  output += pc.cyan("https://github.com/AmanVarshney01/create-better-t-stack");
5773
5754
  consola$1.box(output);
5774
5755
  }
@@ -6096,7 +6077,7 @@ async function createProjectHandler(input) {
6096
6077
  const startTime = Date.now();
6097
6078
  const timeScaffolded = (/* @__PURE__ */ new Date()).toISOString();
6098
6079
  if (input.renderTitle !== false) renderTitle();
6099
- intro(pc.magenta("Creating a new Better-T Stack project"));
6080
+ intro(pc.magenta("Creating a new Better-T-Stack project"));
6100
6081
  if (input.yolo) consola.fatal("YOLO mode enabled - skipping checks. Things may break!");
6101
6082
  let currentPathInput;
6102
6083
  if (input.yes && input.projectName) currentPathInput = input.projectName;
@@ -6170,10 +6151,7 @@ async function createProjectHandler(input) {
6170
6151
  projectDir: finalResolvedPath,
6171
6152
  relativePath: finalPathInput
6172
6153
  };
6173
- coerceBackendPresets(config);
6174
6154
  validateConfigCompatibility(config, providedFlags, cliInput);
6175
- if (config.backend === "convex") log.info(`Due to '--backend convex' flag, the following options have been automatically set: database=none, orm=none, api=none, runtime=none, dbSetup=none, examples=todo`);
6176
- else if (config.backend === "none") log.info("Due to '--backend none', the following options have been automatically set: --auth none, --database=none, --orm=none, --api=none, --runtime=none, --db-setup=none, --examples=none");
6177
6155
  log.info(pc.yellow("Using default/flag options (config prompts skipped):"));
6178
6156
  log.message(displayConfig(config));
6179
6157
  log.message("");
@@ -6246,7 +6224,7 @@ async function addAddonsHandler(input) {
6246
6224
  try {
6247
6225
  const projectDir = input.projectDir || process.cwd();
6248
6226
  const detectedConfig = await detectProjectConfig(projectDir);
6249
- if (!detectedConfig) exitWithError("Could not detect project configuration. Please ensure this is a valid Better-T Stack project.");
6227
+ if (!detectedConfig) exitWithError("Could not detect project configuration. Please ensure this is a valid Better-T-Stack project.");
6250
6228
  if (!input.addons || input.addons.length === 0) {
6251
6229
  const addonsPrompt = await getAddonsToAdd(detectedConfig.frontend || [], detectedConfig.addons || []);
6252
6230
  if (addonsPrompt.length > 0) input.addons = addonsPrompt;
@@ -6370,7 +6348,7 @@ function displaySponsors(sponsors$1) {
6370
6348
  const t = trpcServer.initTRPC.create();
6371
6349
  const router = t.router({
6372
6350
  init: t.procedure.meta({
6373
- description: "Create a new Better-T Stack project",
6351
+ description: "Create a new Better-T-Stack project",
6374
6352
  default: true,
6375
6353
  negateBooleans: true
6376
6354
  }).input(z.tuple([ProjectNameSchema.optional(), z.object({
@@ -6404,7 +6382,7 @@ const router = t.router({
6404
6382
  const result = await createProjectHandler(combinedInput);
6405
6383
  if (options.verbose) return result;
6406
6384
  }),
6407
- add: t.procedure.meta({ description: "Add addons or deployment configurations to an existing Better-T Stack project" }).input(z.tuple([z.object({
6385
+ add: t.procedure.meta({ description: "Add addons or deployment configurations to an existing Better-T-Stack project" }).input(z.tuple([z.object({
6408
6386
  addons: z.array(AddonsSchema).optional().default([]),
6409
6387
  webDeploy: WebDeploySchema.optional(),
6410
6388
  serverDeploy: ServerDeploySchema.optional(),
@@ -6415,17 +6393,17 @@ const router = t.router({
6415
6393
  const [options] = input;
6416
6394
  await addAddonsHandler(options);
6417
6395
  }),
6418
- sponsors: t.procedure.meta({ description: "Show Better-T Stack sponsors" }).mutation(async () => {
6396
+ sponsors: t.procedure.meta({ description: "Show Better-T-Stack sponsors" }).mutation(async () => {
6419
6397
  try {
6420
6398
  renderTitle();
6421
- intro(pc.magenta("Better-T Stack Sponsors"));
6399
+ intro(pc.magenta("Better-T-Stack Sponsors"));
6422
6400
  const sponsors$1 = await fetchSponsors();
6423
6401
  displaySponsors(sponsors$1);
6424
6402
  } catch (error) {
6425
6403
  handleError(error, "Failed to display sponsors");
6426
6404
  }
6427
6405
  }),
6428
- docs: t.procedure.meta({ description: "Open Better-T Stack documentation" }).mutation(async () => {
6406
+ docs: t.procedure.meta({ description: "Open Better-T-Stack documentation" }).mutation(async () => {
6429
6407
  const DOCS_URL = "https://better-t-stack.dev/docs";
6430
6408
  try {
6431
6409
  await openUrl(DOCS_URL);
@@ -6453,7 +6431,7 @@ function createBtsCli() {
6453
6431
  });
6454
6432
  }
6455
6433
  /**
6456
- * Initialize a new Better-T Stack project
6434
+ * Initialize a new Better-T-Stack project
6457
6435
  *
6458
6436
  * @example CLI usage:
6459
6437
  * ```bash
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.38.1",
3
+ "version": "2.39.0-canary.bae99c30",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Aman Varshney",
8
8
  "bin": {
9
- "create-better-t-stack": "dist/cli.js"
9
+ "create-better-t-stack": "./src/cli.ts"
10
10
  },
11
11
  "files": [
12
12
  "templates",
@@ -59,8 +59,7 @@
59
59
  },
60
60
  "exports": {
61
61
  ".": {
62
- "types": "./dist/index.d.ts",
63
- "import": "./dist/index.js"
62
+ "import": "./src/index.ts"
64
63
  }
65
64
  },
66
65
  "dependencies": {
@@ -0,0 +1,22 @@
1
+ "use client";
2
+
3
+ import { type ComponentProps, memo } from "react";
4
+ import { Streamdown } from "streamdown";
5
+ import { cn } from "@/lib/utils";
6
+
7
+ type ResponseProps = ComponentProps<typeof Streamdown>;
8
+
9
+ export const Response = memo(
10
+ ({ className, ...props }: ResponseProps) => (
11
+ <Streamdown
12
+ className={cn(
13
+ "size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
14
+ className,
15
+ )}
16
+ {...props}
17
+ />
18
+ ),
19
+ (prevProps, nextProps) => prevProps.children === nextProps.children,
20
+ );
21
+
22
+ Response.displayName = "Response";
@@ -2,10 +2,11 @@
2
2
 
3
3
  import { useChat } from "@ai-sdk/react";
4
4
  import { DefaultChatTransport } from "ai";
5
- import { Input } from "@/components/ui/input";
6
- import { Button } from "@/components/ui/button";
7
5
  import { Send } from "lucide-react";
8
- import { useRef, useEffect, useState } from "react";
6
+ import { useEffect, useRef, useState } from "react";
7
+ import { Response } from "@/components/response";
8
+ import { Button } from "@/components/ui/button";
9
+ import { Input } from "@/components/ui/input";
9
10
 
10
11
  export default function AIPage() {
11
12
  const [input, setInput] = useState("");
@@ -51,11 +52,7 @@ export default function AIPage() {
51
52
  </p>
52
53
  {message.parts?.map((part, index) => {
53
54
  if (part.type === "text") {
54
- return (
55
- <div key={index} className="whitespace-pre-wrap">
56
- {part.text}
57
- </div>
58
- );
55
+ return <Response key={index}>{part.text}</Response>;
59
56
  }
60
57
  return null;
61
58
  })}
@@ -4,6 +4,7 @@ import { DefaultChatTransport } from "ai";
4
4
  import { Input } from "@/components/ui/input";
5
5
  import { Button } from "@/components/ui/button";
6
6
  import { Send } from "lucide-react";
7
+ import { Response } from "@/components/response";
7
8
 
8
9
  const AI: React.FC = () => {
9
10
  const [input, setInput] = useState("");
@@ -49,11 +50,7 @@ const AI: React.FC = () => {
49
50
  </p>
50
51
  {message.parts?.map((part, index) => {
51
52
  if (part.type === "text") {
52
- return (
53
- <div key={index} className="whitespace-pre-wrap">
54
- {part.text}
55
- </div>
56
- );
53
+ return <Response key={index}>{part.text}</Response>;
57
54
  }
58
55
  return null;
59
56
  })}
@@ -5,6 +5,7 @@ import { Input } from "@/components/ui/input";
5
5
  import { Button } from "@/components/ui/button";
6
6
  import { Send } from "lucide-react";
7
7
  import { useRef, useEffect, useState } from "react";
8
+ import { Response } from "@/components/response";
8
9
 
9
10
  export const Route = createFileRoute("/ai")({
10
11
  component: RouteComponent,
@@ -54,11 +55,7 @@ function RouteComponent() {
54
55
  </p>
55
56
  {message.parts?.map((part, index) => {
56
57
  if (part.type === "text") {
57
- return (
58
- <div key={index} className="whitespace-pre-wrap">
59
- {part.text}
60
- </div>
61
- );
58
+ return <Response key={index}>{part.text}</Response>;
62
59
  }
63
60
  return null;
64
61
  })}
@@ -5,6 +5,7 @@ import { Input } from "@/components/ui/input";
5
5
  import { Button } from "@/components/ui/button";
6
6
  import { Send } from "lucide-react";
7
7
  import { useRef, useEffect, useState } from "react";
8
+ import { Response } from "@/components/response";
8
9
 
9
10
  export const Route = createFileRoute("/ai")({
10
11
  component: RouteComponent,
@@ -54,11 +55,7 @@ function RouteComponent() {
54
55
  </p>
55
56
  {message.parts?.map((part, index) => {
56
57
  if (part.type === "text") {
57
- return (
58
- <div key={index} className="whitespace-pre-wrap">
59
- {part.text}
60
- </div>
61
- );
58
+ return <Response key={index}>{part.text}</Response>;
62
59
  }
63
60
  return null;
64
61
  })}
@@ -1,5 +1,8 @@
1
1
  @import "tailwindcss";
2
2
  @import "tw-animate-css";
3
+ {{#if (includes examples "ai")}}
4
+ @source "../node_modules/streamdown/dist/index.js";
5
+ {{/if}}
3
6
 
4
7
  @custom-variant dark (&:where(.dark, .dark *));
5
8