OpenTownieuseChatLogic.ts4 matches
6project: any;
7branchId: string | undefined;
8anthropicApiKey: string;
9bearerToken: string;
10selectedFiles: string[];
16project,
17branchId,
18anthropicApiKey,
19bearerToken,
20selectedFiles,
35status,
36} = useChat({
37api: "/api/send-message",
38body: {
39project,
40branchId,
41anthropicApiKey,
42selectedFiles,
43images: images
OpenTownieTODOs.md1 match
7- [ ] Rebuild as React Router?
8- [ ] opentownie as a pr bot
9- [ ] give it the ability to see its own client-side and server-side logs by building a middleware that shoves them into a SQL light database date and then give it a tool to access them or use our trpc API in that tool
10- [ ] do a browser use or screenshot thing to give it access to its own visual output
11- [ ] Have it default to creating a new branch off main and then embedding and iframe to the resulting http val and give you a link to a pr opening url
OpenTowniesystem_prompt.txt7 matches
98- For AI-generated images, use: `https://maxm-imggenurl.web.val.run/the-description-of-your-image`
99- **Storage:** DO NOT use the Deno KV module for storage
100- **Browser APIs:** DO NOT use the `alert()`, `prompt()`, or `confirm()` methods
101- **Weather Data:** Use open-meteo for weather data (doesn't require API keys) unless otherwise specified
102- **View Source:** Add a view source link with `import.meta.url.replace("esm.town", "val.town")` and include `target="_top"` attribute
103- **Error Debugging:** Add `<script src="https://esm.town/v/std/catch"></script>` to HTML to capture client-side errors
104- **Error Handling:** Only use try...catch when there's a clear local resolution; avoid catches that merely log or return 500s - let errors bubble up with full context
105- **Environment Variables:** Use `Deno.env.get('keyname')` and minimize their use - prefer APIs without keys
106- **Imports:** Use `https://esm.sh` for npm and Deno dependencies to ensure compatibility on server and browser
107- **Storage Strategy:** Only use backend storage if explicitly required; prefer simple static client-side sites
188189### Backend (Hono) Best Practices
190- Hono is the recommended API framework (similar to Express, Flask, or Sinatra)
191- Main entry point should be `backend/index.ts`
192- **Static asset serving:** Use the utility functions to read and serve project files:
209});
210```
211- Create RESTful API routes for CRUD operations
212- Be careful with error handling as Hono tends to swallow errors
213- Consider re-throwing errors to see full stack traces:
226- Use React 18.2.0 consistently in all imports and the `@jsxImportSource` pragma
227- Follow the React component pattern from the example project
228- Handle API calls properly with proper error catching
229230### Database Patterns
257- For files in the project, use `readFile` helpers
2582595. **API Design:**
260- `fetch` handler is the entry point for HTTP vals
261- Run the Hono app with `export default app.fetch // This is the entry point for HTTP vals`
OpenTowniesoundEffects.ts4 matches
45/**
6* Plays a bell sound notification using the Web Audio API
7* @returns A Promise that resolves when the sound has started playing
8*/
13const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
14if (!AudioContext) {
15console.warn("Web Audio API not supported in this browser");
16resolve();
17return;
6566/**
67* Plays a simple notification sound using the Web Audio API
68* This is a simpler, shorter bell sound
69* @returns A Promise that resolves when the sound has started playing
75const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
76if (!AudioContext) {
77console.warn("Web Audio API not supported in this browser");
78resolve();
79return;
OpenTowniesend-message.ts11 matches
18}
1920const { messages, project, branchId, anthropicApiKey, selectedFiles, images } = await c.req.json();
21console.log("Original messages:", JSON.stringify(messages, null, 2));
22console.log("Images received:", JSON.stringify(images, null, 2));
2324// Check if API key is available
25if (!anthropicApiKey) {
26return Response.json({
27error: "Anthropic API key is required. Please log out and add your Anthropic API key to use this app.",
28}, { status: 400 });
29}
3031let apiKey;
32if (!anthropicApiKey) {
33return Response.json({
34error: "Anthropic API key is required. Please log out and add your Anthropic API key to use this app.",
35}, { status: 400 });
36} else if (anthropicApiKey === Deno.env.get("PASSWORD")) {
37apiKey = Deno.env.get("PROVIDED_ANTHROPIC_API_KEY");
38} else {
39apiKey = anthropicApiKey;
40}
4142const anthropic = createAnthropic({
43apiKey,
44});
45
OpenTownieREADME.md11 matches
9- **File Browser**: Select specific files to include in the context window for more focused AI assistance
10- **Branch Management**: View, select, and create branches without leaving the app
11- **Cost Tracking**: See estimated API usage costs for each interaction
12- **Sound Notifications**: Get alerted when Claude finishes responding
13- **Mobile-Friendly**: Works on both desktop and mobile devices
15## How It Works
16171. **Login**: Authenticate with your Val Town API token and Anthropic API key
182. **Select a Project**: Choose which Val Town project you want to work on
193. **Select Files**: Browse your project files and select which ones to include in the context window
25### Prerequisites
2627- A Val Town account with API access
28- An Anthropic API key (Claude 3.7 Sonnet)
2930### Setup
31321. Visit the OpenTownie app
332. Enter your Val Town API token (with `projects:write` and `users:read` permissions)
343. Enter your Anthropic API key
354. Click "Login" to access your projects
3647OpenTownie is built with:
48- React frontend with TypeScript
49- Hono API server backend
50- Tailwind CSS for styling
51- Web Audio API for sound notifications
52- AI SDK for Claude integration
5354The application proxies requests to the Anthropic API and Val Town API, allowing Claude to view and edit your project files directly.
5556## Privacy & Security
5758- Your Val Town API token and Anthropic API key are stored locally in your browser
59- No data is stored on our servers
60- All communication with the APIs is done directly from your browser
OpenTownieProjects.tsx1 match
1011async function loader({ bearerToken }: { bearerToken: string }) {
12const data = await (await fetch("/api/projects-loader", {
13headers: {
14"Authorization": "Bearer " + bearerToken,
OpenTownieLogin.tsx6 matches
4export function Login() {
5const [bearerToken, setBearerToken] = useLocalStorage("bearer", "");
6const [anthropicApiKey, setAnthropicApiKey] = useLocalStorage("anthropic_api_key", "");
78return (
11<div className="space-y-2">
12<label className="block text-sm font-medium text-gray-700">
13<a target="_blank" href="https://www.val.town/settings/api" className="underline hover:text-slate-400">
14Val Town API Token
15</a>
16{""}(with <code>projects:write</code> and <code>users:read</code> permission)
26</div>
27<div className="space-y-2">
28<label className="block text-sm font-medium text-gray-700">Anthropic API Key</label>
29<input
30type="password"
31value={anthropicApiKey}
32onChange={(e: any) => setAnthropicApiKey(e.target.value)}
33placeholder="sk-ant-xxxxx"
34autoComplete="off"
OpenTownieindex.ts1 match
4const app = new Hono();
56app.route("/api", backend);
7app.get("/", async (c) => {
8return c.html(
OpenTownieDirectoryTree.tsx1 match
236];
237238// Capitalize first letter
239if (num >= 0 && num <= 10) {
240const word = words[num];