Trending Vals
2
mewtru
valentine
HTTP
Hello!!! Feel free to mess around with this val and make it your own :). Just click on "Fork" in the top right. You can change the phrases that show up as you click no, you can change the firstImg and secondImg, maybe even add more images. And you can also change the colors and any of the text on the screen! Have fun with it and hopefully your crush says yes hehe.
9
4
nbbaier
sqliteExplorerApp
HTTP
SQLite Explorer View and interact with your Val Town SQLite data. It's based off Steve's excellent SQLite Admin val, adding the ability to run SQLite queries directly in the interface. This new version has a revised UI and that's heavily inspired by LibSQL Studio by invisal . This is now more an SPA, with tables, queries and results showing up on the same page. Install Install the latest stable version (v86) by forking this val: Authentication Login to your SQLite Explorer with password authentication with your Val Town API Token as the password. Todos / Plans [ ] improve error handling [ ] improve table formatting [ ] sticky table headers [x] add codemirror [ ] add loading indication to the run button (initial version shipped) [ ] add ability to favorite queries [ ] add saving of last query run for a table (started) [ ] add visible output for non-query statements [ ] add schema viewing [ ] add refresh to table list sidebar after CREATE/DROP/ALTER statements [ ] add automatic execution of initial select query on double click [x] add views to the sidebar [ ] add triggers to sidebar [ ] add upload from SQL, CSV and JSON [ ] add ability to connect to a non-val town Turso database [x] fix wonky sidebar separator height problem (thanks to @stevekrouse) [x] make result tables scrollable [x] add export to CSV, and JSON (CSV and JSON helper functions written in this val . Thanks to @pomdtr for merging the initial version!) [x] add listener for cmd+enter to submit query
23
7
fiberplane
fiberplaneHonoStarter
HTTP
Example Hono app with a Fiberplane API explorer. For an example with OpenApiHono , see: https://www.val.town/v/fiberplane/fiberplaneHonoOpenApiStarter Import @fiberplane/hono import {
createFiberplane,
createOpenAPISpec
} from "https://esm.sh/@fiberplane/[email protected]"; Generate a simplified API spec (if you don't already have one) app.get("/openapi.json", async (c) => {
const spec = createOpenAPISpec(app, {
info: { title: "My Hono API", version: "1.0.0" },
});
return c.json(spec);
}); Mount the api explorer import { createFiberplane, createOpenAPISpec } from "https://esm.sh/@fiberplane/[email protected]";
import { Hono } from "https://esm.sh/[email protected]";
const app = new Hono();
// ... Define your api routes here!
app.use(
"/*",
createFiberplane({
openapi: { url: "/openapi.json" },
}),
);
export default app.fetch; Visit your Val's root route to play with the API explorer! How it Works createFiberplane mounts a UI at the root route ( / ), which can be used to explore the api's routes and make requests.
Think of it like an embedded, lightweigh postman. If you don't have an API spec at the ready, then the createOpenAPISpec utility helps create a simple OpenAPI spec from all routes in the application.
( Note that this simple spec does not include information on expected query parameters, headers, or payloads! )
4
8
valdottown
templateTwitterAlert
Cron
Twitter/𝕏 Keyword Alerts [TEMPLATE] Get custom notifications when you, your company, or anything you care about is mentioned on Twitter/X, even if they don't tag you directly. This template will help you: Search for specific mentions on Twitter/X using customizable keywords. Deliver notifications wherever you'd like (email, Discord, Slack, Telegram, etc). Example This val tracks mentions of "Val Town" and related terms, excluding noise like retweets and irrelevant accounts. Notifications are sent to a Discord webhook but can be easily reconfigured for other platforms.
To see exactly how we use this template at Val Town: https://www.val.town/v/stevekrouse/twitterAlert Set Up 1. Fork this Val To use this template, fork this val on the top right corner of this page.
2. View Source Code The CODE box shows you the the full source code of this val, you may need to scroll down to see it.
3. Customize Query Define what you want to search for by modifying query : const query = "\"val.town\" OR \"val.run\" OR \"val town\" -_ValTown_ -is:retweet -from:valenzuelacity -from:val__run"; Refer to Twitter's search operators to fine-tune your query. 4. Test API call Set isProd = false in the code if you are testing, to ensure there are enough tweets to display.
Toggle it back to true when you're ready to run this cron job in production and actuall send notifications. 5. Choose Notification Method This template uses a Discord webhook for notifications, but
you can update this to your preferred platform by replacing the discordWebhook call
with a call to Slack , @std/email , etc. Create a Discord webhook following this guide . Save your Discord Webhook URL in your Val Town environment variables : Key: mentionsDiscord Value: Your Discord webhook URL.
Notifications will be sent using this function: await discordWebhook({
url: Deno.env.get("mentionsDiscord"),
content,
}); 🎉 Congrats! You now have a val running that ensures you never miss another Twitter/X mention. 🎉 NOTE: Usage Limits This val uses the SocialData API for Twitter data: Proxies via Val Town's SocialDataProxy : Limited to 10 cents per day for Val Town Pro users . This API is only for Pro users. Need more calls? Sign up for your own SocialData API token and configure the socialDataSearch function.
0
9

stevekrouse
discordWebhook
Script
Send a Discord message Send a message to a Discord channel from Val Town. It's useful for notifying your team or community when someone interesting happens, like a user signup, Stripe payment, mention on social media, etc. import { discordWebhook } from "https://esm.town/v/stevekrouse/discordWebhook";
await discordWebhook({
url: Deno.env.get("engDiscord"),
content: "Hi from val town!",
});
Example val: https://www.val.town/v/stevekrouse.discordWebhookEx Setup 1. Create a Discord Webhook Follow the instructions here: https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks It really only takes 2 minutes. 2. Copy webhook URL Paste it into your secrets as discordWebhook . 3. Send a message! import { discordWebhook } from "https://esm.town/v/stevekrouse/discordWebhook";
await discordWebhook({
url: Deno.env.get("engDiscord"),
content: "Hi from val town!",
}); Example val: https://www.val.town/v/stevekrouse.discordWebhookEx
1
10
valdottown
templateHackerNewsAlert
Cron
Hacker News Keyword Alerts [TEMPLATE] Get notifications when specific keywords appear in Hacker News posts. This template will help you: Search Hacker News for specific keywords. Send notifications to your preferred platform (Discord, Slack, email, etc.), the default in this template is Discord. Example This val tracks mentions of "Val Town" on Hacker News and sends updates to a Discord webhook.
Set Up 1. Fork this Val To start using this template, fork this val by clicking the fork button at the top-right corner of the page.
2. View Source Code The CODE box shows you the the full source code of this val, you may need to scroll down to see it.
3. Customize Keyword In the CODE box below, update the terms or phrases you want to track:
query: '"val town" || "val.town"' 5. Set Up Your Notification Method This template uses a Discord webhook for notifications. You can update this to your preferred platform: Create a Discord webhook following this guide .
Save your webhook URL in your Val Town environment variables: Key: mentionsDiscord Value: Your Discord webhook URL.
Notifications will be sent using this function: await discordWebhook({
url: Deno.env.get("mentionsDiscord"),
content,
}); To switch to another platform (e.g., Slack, email, or custom webhooks), replace the discordWebhook call with the appropriate integration ((e.g., @std/email , Slack , or anywhere else ) 🎉 Congrats! You now have a val running that ensures you never miss another Hacker News mention. 🎉
0
11
13

stevekrouse
fileToDataURL
Script
File to Data URL Helpers to convert files to base64 & base64-encoded data URLs,
which are particularly helpful for sending images to LLMs
like ChatGPT, Anthropic, and Google. ChatGPT Live example import { fileToDataURL } from "https://esm.town/v/stevekrouse/fileToDataURL";
const dataURL = await fileToDataURL(file);
const response = await chat([
{
role: "system",
content: `You are an nutritionist.
Estimate the calories.
We only need a VERY ROUGH estimate.
Respond ONLY in a JSON array with values conforming to: {ingredient: string, calories: number}
`,
},
{
role: "user",
content: [{
type: "image_url",
image_url: {
url: dataURL,
},
}],
},
], {
model: "gpt-4o",
max_tokens: 200,
}); Anthropic Live example import { fileToBase64 } from "https://esm.town/v/stevekrouse/fileToDataURL";
const base64File = await fileToBase64(file);
let res = await anthropic.messages.create({
model: "claude-3-5-sonnet-20240620",
max_tokens: 1024,
messages: [
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": file.type,
"data": base64File,
},
},
{
"type": "text",
"text": `Write an HTML email
that evokes this photo in the funniest
way possible, with code fences.`,
},
],
},
],
}); Google Live example import { fileToBase64 } from "https://esm.town/v/stevekrouse/fileToDataURL";
const base64Image = await fileToBase64(image);
const result = await model.generateContent([
"Write all the names and authors of these books in JSON format. The response should be a valid JSON array of objects, each with 'title' and 'author' properties.",
{
inlineData: {
data: base64Image,
mimeType: image.type,
},
},
]);
3
14
15
16
michaelfromyeg
notion2wallabag
HTTP
Notion2Wallabag Intended to be run with Notion's webhooks. When fired, tries to save a Notion database item with a "Link" property to a Wallabag instance. Cannot be re-used for other workspaces, since it requires various Wallabag secrets and a Notion-specific token. Feel free to fork!
2
17
minhee
blob_kv
Script
BlobKvStore : Fedify KvStore implementation for Val Town This module provides the BlobVKvStore class, a KvStore implementation
built on top of Val Town's blob storage . Here's how to use: import { createFederation } from "jsr:@fedify/fedify@^1.4.3";
import { BlobKvStore } from "https://esm.town/v/minhee/blob_kv";
import { blob } from "https://esm.town/v/std/blob";
const federation = createFederation<void>({
kv: new BlobKvStore(blob),
});
1
18

steveruizok
tldraw_computer_example
HTTP
tldraw computer custom endpoint example This val is an example custom endpoint for tldraw computer 's data component. Usage To use this val with tldraw.computer, follow these steps: Fork this Val. Click the Copy endpoint button on your new Val. Open a project on tldraw.computer Create a Data component in your tldraw computer project In the Source dropdown, select Custom and the POST method Paste the endpoint into Data component's the HTTP Endpoint input. Run the component. To see the output, connect the Data component to a Text component. How it works In tldraw computer, you can configure a Data component to use a custom HTTP endpoint as its data source. You can also configure the request method, either GET or POST. If a Data component's request method is POST, then when the component next updates, it will send a POST request to the endpoint. The request's body will contain an array of the Data objects that the component had received as inputs. If the request method if GET, then the component will only make the request—its body will be empty. In both cases, the component will expect back a response that includes an array of Data objects these objects will be passed along as the data component's outputs. The endpoint (your forked version of this Val) can do whatever it likes between the request and response, but the response must include data in the correct format. If the format is wrong, the computer app will create a text data object instead that includes the response as plain text. Support If you're running into any difficulties, check out the #tldraw-computer channel on the tldraw discord.
4
19
g
vtdb
Script
Val Town Database This val exports vtdb , a correctly typed Kysely instance
to query the @sqlite.db database containing public vals. Example usage: import { vtdb } from 'https://esm.town/v/g/vtdb';
const vals = await vtdb.selectFrom('vals')
.selectAll()
.orderBy('created_at desc')
.limit(5)
.execute();
console.log(vals.map((val) => val.name));
4
20
paulkinlan
emailSummaryHandler
Email
Email Summary Service This val is an email handler replies to emails it recieves with an LLM-generated summary. To use, forward an email to [email protected] Blog post: https://paul.kinlan.me/projects/email-summary-service/
4
24
andreterron
codeOnValTown
Script
Code on Val Town Adds a "Code on Val Town" ribbon to your page. This lets your website visitors navigate to the code behind it. This uses github-fork-ribbon-css under the hood. Usage Here are 2 different ways to add the "Code on Val Town" ribbon: 1. Wrap your fetch handler (recommended) import { modifyFetchHandler } from "https://esm.town/v/andreterron/codeOnValTown?v=50";
import { html } from "https://esm.town/v/stevekrouse/html?v=5";
export default modifyFetchHandler(async (req: Request): Promise<Response> => {
return html(`<h2>Hello world!</h2>`);
}); Example: @andreterron/openable_handler 2. Wrap your HTML string import { modifyHtmlString } from "https://esm.town/v/andreterron/codeOnValTown?v=50";
import { html } from "https://esm.town/v/stevekrouse/html?v=5";
export default async (req: Request): Promise<Response> => {
return html(modifyHtmlString(`<h2>Hello world!</h2>`));
}; Example: @andreterron/openable_html Other ways We made sure this was very modular, so you can also add the ribbon using these methods: Get the element string directly: @andreterron/codeOnVT_ribbonElement Modify an HTTP Response: @andreterron/codeOnVT_modifyResponse Use .pipeThrough to append to a stream: @andreterron/InjectCodeOnValTownStream Customization Linking to the val These functions infer the val using the call stack or the request URL. If the inference isn't working, or if you want to ensure it links to a specific val, pass the val argument: modifyFetchHandler(handler, {val: { handle: "andre", name: "foo" }}) modifyHtmlString("<html>...", {val: { handle: "andre", name: "foo" }}) Styling You can set the style parameter to a css string to customize the ribbon. Check out github-fork-ribbon-css to learn more about how to style the element. modifyFetchHandler(handler, {style: ".github-fork-ribbon:before { background-color: #333; }"}) modifyHtmlString("<html>...", {style: ".github-fork-ribbon:before { background-color: #333; }"}) Here's how you can hide the ribbon on small screens: modifyFetchHandler(handler, {style: `@media (max-width: 768px) {
.github-fork-ribbon {
display: none !important;
}
}`}) To-dos [ ] Let users customize the ribbon. Some ideas are the text, color or placement.
5
25
alexwein
loopyLetters
HTTP
[WIP] Loopy Letters, another little word game A word game with a small gameplay loop. Plays best on your phone. It uses random words from the Wordnik word game list, as shared on their Github page ,
which has a lot of stuff on there I myself wouldn't really consider a word. Sorry about that. I probably spent as much time prompting the Townie LLM interface as I did in the code editor.
So if parts seem sloppy, it's because it is slop. Rules Use every letter on the donut to spell a word. Letters in the word must be adjacent to each other on the donut. You can go clockwise or counterclockwise . When you find a word. The next word to find appears. Go fast. Go slow. Enjoy. This revisits the gameplay from a 2002 Observable notebook I made called
"find a (big) word, rings" .
1
26

pomdtr
password_auth
Script
Password Auth Middleware Protect your vals behind a password. Use session cookies to persist authentication. Usage import { passwordAuth } from "https://esm.town/v/pomdtr/password_auth?v=84";
export default passwordAuth(() => {
return new Response("OK");
}, { verifyPassword: (password) => password == Deno.env.get("VAL_PASSWORD") }); If you want to use an api token to authenticate: import { passwordAuth } from "https://esm.town/v/pomdtr/password_auth?v=84";
import { verifyToken } from "https://esm.town/v/pomdtr/verifyToken";
export default passwordAuth(() => {
return new Response("OK");
}, { verifyPassword: verifyToken }); TODO [x] allow to authenticate using a val town token [ ] add a way to send an email to ask a password from the val owner [ ] automatically extend the session [ ] automatically remove expired sessions FAQ How to sign out ? Navigate to <your-site>/signout .
15
27

stevekrouse
umbrellaReminder
Cron
☔️ Umbrella reminder if there's rain today Setup Fork this val 👉 https://val.town/v/stevekrouse.umbrellaReminder/fork Customize the location (line 8). You can supply any free-form description of a location. ⚠️ Only works for US-based locations (where weather.gov covers). How it works Geocodes an free-form description of a location to latitude and longitude – @stevekrouse.nominatimSearch Converts a latitude and longitude to weather.gov grid – @stevekrouse.weatherGovGrid Gets the hourly forecast for that grid Filters the forecast for periods that are today and >30% chance of rain If there are any, it formats them appropriately, and sends me an email
9
28
30
sarahxc
slackScout
Cron
Slack scout sends a slack notification every time your keywords are mentioned on Twitter, Hacker News, or Reddit. Get notified whenever you, your company, or topics of interest are mentioned online. Built with Browserbase . Inspired by f5bot.com . Full code tutorial . Getting Started To run Slack Scout, you’ll need a Browserbase API key Slack Webhook URL: setup here Twitter Developer API key Browserbase Browserbase is a developer platform to run, manage, and monitor headless browsers at scale. We’ll use Browserbase to navigate to, and scrape our different news sources. We’ll also use Browserbase’s Proxies to ensure we simulate authentic user interactions across multiple browser sessions . Get started with Browserbase for free here . Twitter We’ve decided to use the Twitter API to include Twitter post results. It costs $100 / month to have a Basic Twitter Developer account. If you decide to use Browserbase, we can lend our token. Comment below for access. Once you have the SLACK_WEBHOOK_URL , BROWSERBASE_API_KEY , and TWITTER_BEARER_TOKEN , input all of these as Val Town Environment Variables . Project created by Sarah Chieng and Alex Phan 💌
15