54- **Storage**: Val Town Blob storage for audio files
55- **AI**: OpenAI Whisper for transcription
56- **Frontend**: React with TypeScript
57- **Styling**: TailwindCSS
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React from "https://esm.sh/react@18.2.0";
3import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
4import App from "./components/App.tsx";
5
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useEffect, useState } from "https://esm.sh/react@18.2.0";
3import type { VoiceNote } from "../../shared/types.ts";
4
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useEffect, useState } from "https://esm.sh/react@18.2.0";
3import Dashboard from "./Dashboard.tsx";
4import VoicePlayer from "./VoicePlayer.tsx";
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import { marked } from "https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js";
3import React, { useEffect, useRef, useState } from "https://esm.sh/react@18.2.0";
4import { MCPClient } from "../utils/MCPClient.ts";
5import { Message } from "./App.tsx";
1/** @jsxImportSource https://esm.sh/react@19 */
2import React from "https://esm.sh/react@19";
3import { type Message, MESSAGE_LIMIT } from "../../shared/utils.ts";
4import { MessageInput } from "./MessageInput.tsx";
9) {
10 const { data: messages = [], isLoading, error } = useMessages(initialMessages);
11 const messagesEndRef = React.useRef<HTMLDivElement>(null);
12
13 const scrollToBottom = () => {
15 };
16
17 React.useEffect(() => {
18 scrollToBottom();
19 }, [messages]);
1/** @jsxImportSource https://esm.sh/react@19 */
2import React from "https://esm.sh/react@19";
3import {
4 RootRoute,
7 createRouter,
8 RouterProvider,
9} from "https://esm.sh/@tanstack/react-router@^1.121.0?deps=react@19";
10import {
11 QueryClient,
12 QueryClientProvider,
13} from "https://esm.sh/@tanstack/react-query@^5.0.0?deps=react@19";
14import { App } from "./components/App.tsx";
15
53
54// Register the router for TypeScript
55declare module "@tanstack/react-router" {
56 interface Register {
57 router: typeof router;
1/** @jsxImportSource https://esm.sh/react@19 */
2import React from "https://esm.sh/react@19";
3import { usePostMessage } from "../lib/queries.ts";
4
5export function MessageInput() {
6 const [message, setMessage] = React.useState("");
7 const postMessage = usePostMessage();
8 const textareaRef = React.useRef<HTMLTextAreaElement>(null);
9
10 const adjustTextareaHeight = () => {
16 };
17
18 React.useEffect(() => {
19 adjustTextareaHeight();
20 }, [message]);
21
22 const handleSubmit = async (e: React.FormEvent) => {
23 e.preventDefault();
24 if (!message.trim()) return;
32 };
33
34 const handleKeyDown = (e: React.KeyboardEvent) => {
35 if (e.key === 'Enter' && !e.shiftKey) {
36 e.preventDefault();
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>React Hono Val Town Starter</title>
7 <script src="https://cdn.tailwindcss.com"></script>
8 <link rel="preconnect" href="https://fonts.googleapis.com">
1/** @jsxImportSource https://esm.sh/react@19 */
2import { createRoot } from "https://esm.sh/react-dom@19/client?deps=react@19";
3import type { Message } from "../shared/utils.ts";
4import { RouterApp } from "./router.tsx";