83 <li className="pb-2 sm:pb-1">
84 <span className={dateClass}>2013 Jun -</span>Software Engineer @{" "}
85 <Link href="http://firstround.com/">First Round Capital</Link>
86 </li>
87 <li className="pb-2 sm:pb-1">
1You are an experienced software engineer who focuses on webscraping as a way to
2provide people with easy access to useful information.
3
4You are given a URL to a website, and create an API for accessing that website's
5data through a beautiful typed json interface.
6
1import { tool } from "npm:ai";
2import { z } from "npm:zod";
3import { JSDOM } from "npm:jsdom";
4import { WebsiteInterface } from "../html.ts";
5
3import {
4 createRoute,
5 OpenAPIHono,
6 z,
7} from "https://esm.sh/@hono/zod-openapi@0.18.4";
8import { HTTPException } from "https://esm.sh/hono@4.7.0/http-exception";
9
10// Create the application
11const app = new OpenAPIHono();
12
13// Define and implement the greeting route
14app.openapi(
15 createRoute({
16 method: "get",
19 request: {
20 params: z.object({
21 name: z.coerce.string().openapi({ example: "John" }),
22 }),
23 },
39);
40
41// Create OpenAPI documentation
42app.doc("/openapi.json", {
43 openapi: "3.0.0",
44 info: { title: "Example greet user API", version: "v1.0.0" },
45});
46
47// Swagger UI for documentation
48app.get("/docs", swaggerUI({ url: "/openapi.json" }));
49
50// Mount the Fiberplane UI at the root to be able to test api endpoints
51app.use("/*", createFiberplane({ openapi: { url: "/openapi.json" } }));
52
53// Root path redirects to docs
1// aiSupportAPI.val.ts
2import { aiSupportLogic } from "./aiSupportLogic.val";
3import authenticate from "./auth.val";
80 }
81
82 // GET /meta โ return API metadata and available endpoints
83 if (pathname === "/meta" && req.method === "GET") {
84 const meta = {
85 name: "AI Support Component API",
86 endpoints: [
87 { method: "POST", path: "/refine", description: "Refine and clarify raw input text" },
88 { method: "GET", path: "/logs", description: "View all logged refinements" },
89 { method: "GET", path: "/cache/:key", description: "Retrieve cached result by cache key" },
90 { method: "GET", path: "/status", description: "API health check" },
91 { method: "GET", path: "/meta", description: "List available endpoints and metadata" },
92 ],
102 return new Response("Not Found", { status: 404 });
103 } catch (error) {
104 console.error("API Handler Error:", error);
105 return new Response("Internal Server Error", { status: 500 });
106 }
15app.get("/frontend/**/*", (c) => serveFile(c.req.path, import.meta.url));
16
17// Add your API routes here
18app.get("/api/data", async (c) => {
19 const result = await generateText({
20 model: anthropic("claude-3-7-sonnet-20250219"),
13 <meta property="og:title" content="Survey the space" />
14 <meta property="og:url" content="Survey the space" />
15 <meta property="og:image" content="https://stevekrouse-blob_admin.web.val.run/api/public/survey.jpeg" />
16 <meta property="twitter:title" content="Survey the space" />
17 <meta property="og:type" content="article" />
19 <meta property="twitter:description" content="Survey the space" />
20 <meta name="twitter:card" content="summary_large_image" />
21 <meta name="twitter:image" content="https://stevekrouse-blob_admin.web.val.run/api/public/survey.jpeg" />
22 <meta property="og:url" content="https://stevekrouse.com/proposal" />
23 <link rel="canonical" content="https://stevekrouse.com/proposal" />
29 <img
30 className=" rounded-lg"
31 src="https://stevekrouse-blob_admin.web.val.run/api/public/survey.jpeg"
32 />
33 <em>
1typescript
2const VALID_API_KEY = "your_valid_api_key_here"; // Replace with your actual API key
3
4export function authenticate(req: Request): boolean {
5 const apiKey = req.headers.get("x-api-key");
6 return apiKey === VALID_API_KEY;
7}
8
17โ โโโ database/
18โ โ โโโ queries.ts # SQLite database operations
19โ โโโ index.ts # Hono API server
20โโโ frontend/
21โ โโโ components/
32
33- Uses Hono as the web framework
34- Provides RESTful API endpoints for todo operations
35- Serves the frontend static files
36- Uses Val Town's SQLite for data persistence
40- Built with React
41- Uses Tailwind CSS for styling
42- Communicates with the backend API
43- Implements optimistic UI updates
44
45## API Endpoints
46
47- `GET /api/todos` - Get all todos
48- `GET /api/todos/:id` - Get a specific todo
49- `POST /api/todos` - Create a new todo
50- `PATCH /api/todos/:id` - Update a todo
51- `DELETE /api/todos/:id` - Delete a todo
52
53## Getting Started
3import { Todo, CreateTodoInput, UpdateTodoInput } from "../../shared/types.ts";
4
5// Get the base URL for API requests
6const getApiBaseUrl = () => {
7 // In production, use the current URL
8 return window.location.origin;
17 const [error, setError] = useState<string | null>(null);
18
19 // Fetch todos from the API
20 const fetchTodos = async () => {
21 try {
22 setIsLoading(true);
23 setError(null);
24 const response = await fetch(`${getApiBaseUrl()}/api/todos`);
25 if (!response.ok) {
26 throw new Error("Failed to fetch todos");
44 setIsLoading(true);
45 setError(null);
46 const response = await fetch(`${getApiBaseUrl()}/api/todos`, {
47 method: "POST",
48 headers: {
78 );
79
80 const response = await fetch(`${getApiBaseUrl()}/api/todos/${id}`, {
81 method: "PATCH",
82 headers: {
114 setTodos(todos.filter((todo) => todo.id !== id));
115
116 const response = await fetch(`${getApiBaseUrl()}/api/todos/${id}`, {
117 method: "DELETE",
118 });