blob_adminnapp.tsx19 matches
70const menuRef = useRef(null);
71const isPublic = blob.key.startsWith("__public/");
72const publicUrl = isPublic ? `${window.location.origin}/api/public/${encodeURIComponent(blob.key.slice(9))}` : null;
7374useEffect(() => {
234setLoading(true);
235try {
236const response = await fetch(`/api/blobs?prefix=${encodeKey(searchPrefix)}&limit=${limit}`);
237const data = await response.json();
238setBlobs(data);
261setBlobContentLoading(true);
262try {
263const response = await fetch(`/api/blob?key=${encodeKey(clickedBlob.key)}`);
264const content = await response.text();
265setSelectedBlob({ ...clickedBlob, key: decodeKey(clickedBlob.key) });
275const handleSave = async () => {
276try {
277await fetch(`/api/blob?key=${encodeKey(selectedBlob.key)}`, {
278method: "PUT",
279body: editContent,
287const handleDelete = async (key) => {
288try {
289await fetch(`/api/blob?key=${encodeKey(key)}`, { method: "DELETE" });
290setBlobs(blobs.filter(b => b.key !== key));
291if (selectedBlob && selectedBlob.key === key) {
304const key = `${searchPrefix}${file.name}`;
305formData.append("key", encodeKey(key));
306await fetch("/api/blob", { method: "POST", body: formData });
307const newBlob = { key, size: file.size, lastModified: new Date().toISOString() };
308setBlobs([newBlob, ...blobs]);
326try {
327const fullKey = `${searchPrefix}${key}`;
328await fetch(`/api/blob?key=${encodeKey(fullKey)}`, {
329method: "PUT",
330body: "",
341const handleDownload = async (key) => {
342try {
343const response = await fetch(`/api/blob?key=${encodeKey(key)}`);
344const blob = await response.blob();
345const url = window.URL.createObjectURL(blob);
360if (newKey && newKey !== oldKey) {
361try {
362const response = await fetch(`/api/blob?key=${encodeKey(oldKey)}`);
363const content = await response.blob();
364await fetch(`/api/blob?key=${encodeKey(newKey)}`, {
365method: "PUT",
366body: content,
367});
368await fetch(`/api/blob?key=${encodeKey(oldKey)}`, { method: "DELETE" });
369setBlobs(blobs.map(b => b.key === oldKey ? { ...b, key: newKey } : b));
370if (selectedBlob && selectedBlob.key === oldKey) {
380const newKey = `__public/${key}`;
381try {
382const response = await fetch(`/api/blob?key=${encodeKey(key)}`);
383const content = await response.blob();
384await fetch(`/api/blob?key=${encodeKey(newKey)}`, {
385method: "PUT",
386body: content,
387});
388await fetch(`/api/blob?key=${encodeKey(key)}`, { method: "DELETE" });
389setBlobs(blobs.map(b => b.key === key ? { ...b, key: newKey } : b));
390if (selectedBlob && selectedBlob.key === key) {
399const newKey = key.slice(9); // Remove "__public/" prefix
400try {
401const response = await fetch(`/api/blob?key=${encodeKey(key)}`);
402const content = await response.blob();
403await fetch(`/api/blob?key=${encodeKey(newKey)}`, {
404method: "PUT",
405body: content,
406});
407await fetch(`/api/blob?key=${encodeKey(key)}`, { method: "DELETE" });
408setBlobs(blobs.map(b => b.key === key ? { ...b, key: newKey } : b));
409if (selectedBlob && selectedBlob.key === key) {
554onClick={() =>
555copyToClipboard(
556`${window.location.origin}/api/public/${encodeURIComponent(selectedBlob.key.slice(9))}`,
557)}
558className="text-blue-400 hover:text-blue-300 text-sm"
577>
578<img
579src={`/api/blob?key=${encodeKey(selectedBlob.key)}`}
580alt="Blob content"
581className="max-w-full h-auto"
14751476// Get random quote
1477if (url.pathname === "/api/quote/random" && request.method === "GET") {
1478const randomIndex = Math.floor(Math.random() * quotes.length);
1479const quote = quotes[randomIndex];
14901491// Get quote by index
1492if (url.pathname.startsWith("/api/quote/") && request.method === "GET") {
1493const index = parseInt(url.pathname.split("/").pop());
1494const quote = quotes.find(q => q.index === index);
15151516// Get quotes by tag
1517if (url.pathname === "/api/quote/tag" && request.method === "GET") {
1518const tag = url.searchParams.get("tag");
151915431544// Get quotes by author
1545if (url.pathname === "/api/quote/author" && request.method === "GET") {
1546const author = url.searchParams.get("author");
154715691570// Get top quotes by likes
1571if (url.pathname === "/api/quote/top" && request.method === "GET") {
1572const limit = parseInt(url.searchParams.get("limit") || "10");
157315871588// Search quotes
1589if (url.pathname === "/api/quote/search" && request.method === "GET") {
1590const query = url.searchParams.get("q");
1591
reactHonoStarterDupeSTART_HERE.ts3 matches
8import { serveFile } from "https://esm.town/v/std/utils@85-main/index.ts";
9import { Hono } from "npm:hono";
10import { addApiRoutes } from "./api.ts";
11import type { OnboardingSettings } from "./state.ts"; // Import type for clarity
12import { addTrackerRoute } from "./trackerRoute.ts";
72addTrackerRoute(app);
7374// 2. Add API endpoints used by the tracker (reset, etc.)
75addApiRoutes(app);
7677// 3. Serve static files from the /frontend directory (if you add any)
4const ideas = [
5"a URL shortener",
6"a custom API for your personal website",
7"a weather notification bot",
8"a tool to monitor website uptime",
10"a simple webhook processor",
11"a daily joke emailer",
12"a personal habit tracker API",
13"a stock price alerter",
14"a meeting reminder service",
reactHonoStarterDupestate.ts1 match
1819const STATE_KEY = "onboardingProgressState_v2"; // Key for blob-managed state
20const SETTINGS_OVERRIDE_KEY = "onboardingSettingsOverrides_v1"; // Optional: if you want to allow API overrides
2122// --- Settings Management ---
reactHonoStarterDupeapi.ts3 matches
45/**
6* Adds API routes (/api/...) to the Hono app.
7*/
8export function addApiRoutes(app: Hono) {
9// Endpoint to reset onboarding progress and settings
10app.post("/api/reset", async (c: Context) => {
11try {
12await resetOnboardingState(); // This now resets settings too
reactHonoStarterDupetracker.html5 matches
80</div>
81<!-- Right Actions -->
82<button class="reset-button" onclick="if(confirm('Reset progress flags in START_HERE.ts? (You may need to manually edit the file)')) postApi('/api/reset').then(()=>window.location.reload())" title="Reset onboarding state (clears blob state)">Reset</button>
83</div>
84</div>
85<script>
86// Helper function for API calls
87async function postApi(endpoint) {
88try {
89const response = await fetch(endpoint, { method: 'POST' });
90if (!response.ok) {
91throw new Error(`API Error: ${response.statusText}`);
92}
93return await response.json();
94} catch (error) {
95console.error('API call failed:', error);
96alert('Operation failed: ' + error.message);
97}
reactHonoStarterDupetrackerRoute.ts6 matches
11} from "./state.ts";
1213// Define API routes separately for clarity
14const api = new Hono();
15api.post("/reset", async (c) => {
16await resetOnboardingState();
17console.log("Onboarding state reset via API.");
18return c.json({ success: true, message: "Onboarding reset" });
19});
2021export function addTrackerRoute(app: Hono) {
22// Mount API routes
23app.route("/api", api);
2425app.get("/", async (c: Context) => {
vtProjectSearchweb.http.tsx1 match
1import { handler } from "./api.tsx";
2import { loadTypeaheadDataIntoMemory } from "./db.ts";
3
vtProjectSearchapi.tsx2 matches
13import { searchDocs, searchDocsCount } from "./docsearch.ts";
1415// Handle typeahead API requests
16export function handleTypeahead(req: Request): Response {
17const url = new URL(req.url);
99searchTerm
100? (needFullDocsData
101? searchDocs(searchTerm, page, pageSize, true) // Get full data for docs tab or JSON API
102: searchDocsCount(searchTerm).then(count => ({ results: [], totalResults: count }))) // Just get count for other tabs in HTML view
103: { results: [], totalResults: 0 }