Trending Vals
31
![stevekrouse avatar](https://images.clerk.dev/uploaded/img_2PqHa2Gsy93xQrjh2w78Xu0cChW.jpeg)
pollRSSFeeds
@stevekrouse
Cron
Poll RSS feeds This val periodically polls specified RSS feeds and send the author an email with new items. It checks each feed defined in rssFeeds for new content since the last run and sends an email with the details of the new items. Usage Fork @stevekrouse/rssFeeds and update it with your desired RSS feeds; Fork this val and replace the https://esm.town/v/stevekrouse/rssFeeds import with your newly forked val; Enjoy RSS updates on your email!
32
![stevekrouse avatar](https://images.clerk.dev/uploaded/img_2PqHa2Gsy93xQrjh2w78Xu0cChW.jpeg)
discordWebhook
@stevekrouse
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
33
![stevekrouse avatar](https://images.clerk.dev/uploaded/img_2PqHa2Gsy93xQrjh2w78Xu0cChW.jpeg)
openai
@stevekrouse
Script
OpenAI ChatGPT helper function This val uses your OpenAI token if you have one, and the @std/openai if not, so it provides limited OpenAI usage for free. import { chat } from "https://esm.town/v/stevekrouse/openai";
const { content } = await chat("Hello, GPT!");
console.log(content); import { chat } from "https://esm.town/v/stevekrouse/openai";
const { content } = await chat(
[
{ role: "system", content: "You are Alan Kay" },
{ role: "user", content: "What is the real computer revolution?"}
],
{ max_tokens: 50, model: "gpt-4o" }
);
console.log(content);
34
35
36
38
39
vimarkdown
@jxnblk
HTTP (preview)
vimarkdown Try it now A VIM-mode markdown editor built with Val Town . Features Write markdown in the browser with VIM keybindings Minimal, focused UI Saves to localStorage Multiple color modes Markdown -> HTML preview (⌘+P) NOT mobile-friendly Fork this editor on Val Town to make it your own Inspired by iA Writer
Made by Jxnblk TODO [ ] Add syntax highlighting to frontmatter block [ ] Support multiple fonts
40
![pomdtr avatar](https://images.clerk.dev/oauth_github/img_2RCoAITJZH1QencEgtVjh4Qirj4.jpeg)
sql
@pomdtr
Script
SQL Template Tag Port of blakeembrey/sql-template-tag for usage in val.town. Usage import { sqlite } from "https://esm.town/v/std/sqlite"
import { sql, zip } from "https://esm.town/v/pomdtr/sql"
const query = sql`SELECT * FROM books WHERE author = ${author}`;
console.log(query.sql) // => "SELECT * FROM books WHERE author = ?"
console.log(query.args) // => [author]
const res = await sqlite.execute(query)
console.table(zip(res)) For advanced usage (ex: nesting queries), refer to the project readme .
42
![stevekrouse avatar](https://images.clerk.dev/uploaded/img_2PqHa2Gsy93xQrjh2w78Xu0cChW.jpeg)
dailyStandupBot
@stevekrouse
Cron
Daily Standup Bot Every weekday at 9am EDT send a message to our team's #engineering Discord channel to start a thread to remind us to do our standup. Slack version: @mikker/dailySlackRoundup Note : We started doing in-person standups at Val Town, so this val was unscheduled.
To get it working for you, you'll need to: Fork it Change its type from Script to Cron and set a schedule like 0 13 * * 1-5
43
sendNotification
@gwoods22
Script
Push Notification Sender This val can be used in other vals to send notifications to a segment using OneSignal's REST API This is really handy if you want to send push notifications to your phone without building a native app! I built a barebones React PWA that asks for a password then loads the OneSignal Web SDK that I deployed to Netlify for free. OneSignal has easy to follow docs so you can build this functionality into a React, Angular, Vue app or even Wordpress! Then install the PWA on your platform of choice and you're off to the races! Setup Save your ONESIGNAL_TOKEN and SEGMENT_APPID from OneSignal to your Val Town environment variables Import into another val! import sendNotification from "https://esm.town/v/gwoods22/sendNotification";
44
renderFormAndSaveData
@andreterron
HTTP
Render form and save data This val provides a web-based interface for collecting email addresses. It features a dual-functionality approach: when accessed via a web browser using a GET request, it serves an HTML form where users can submit their email address. If the script receives a POST request, it implies that the form has been submitted, and it proceeds to handle the incoming data. Fork this val to customize it and use it on your account.
46
![samwho avatar](https://images.clerk.dev/oauth_github/img_2RTq0robLbMDZwVqJnG7Dqw8qp1.png)
featureflags
@samwho
HTTP (preview)
Feature Flags This val demonstrates a very simple feature flag implementation. There is a const in the file called FLAGS which stores the feature flags defined, fork this val and modify this value to setup your own flags. Defining flags The example FLAGS value is: const FLAGS: Record<string, Flag> = {
"flag1": Flag.rollout(0.5),
"flag2": Flag.enabled().block("user_123"),
"flag3": Flag.disabled().allow("hello@samwho.dev"),
}; This demonstrates: flag1 -- a flag that will be enabled for 50% of users (more on how users are defined later) flag2 -- a flag that is enabled for everyone except user_123 flag3 -- a flag that is disabled for everyone except hello@samwho.dev Endpoints There are two endpoints: / -- the root endpoint fetches all flags for the given user. /:id -- fetches just one flag value, given by :id , for the given user. Specifying users By default, the user is determined by IP address. If you want to be more specific, you can pass in the ?userId query parameter to any endpoint and that will be used instead. How it works This val works by hashing the userId and using the resulting value to determine whether a flag should be enabled or disabled. In a 50% rollout, for example, the numeric hash of the userId is taken and divided by the maximum hash value. If the result is less than the rollout percentage, the flag is enabled. This allows for completely stateless feature flags, no database required. To prevent the same users getting features first all of the time, the flag name is prepended to the userId before hashing.
47
48
![stevekrouse avatar](https://images.clerk.dev/uploaded/img_2PqHa2Gsy93xQrjh2w78Xu0cChW.jpeg)
umbrellaReminder
@stevekrouse
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
50
52
53
verify_discord_signature
@mattx
Script
verify_discord_signature Verify HTTP signatures coming from Discord. public_key should be the Ed25519 public key from Discord, as a hex string body should be the request body as a string. If you have a JSON object as the request body, use JSON.stringify. signature should be the X-Signature-Ed25519 header timestamp should be the X-Signature-Timestamp header
You must return a 401 error and return early if this function returns false, otherwise you will pretty quickly get a big scary warning from Discord that your endpoint has been removed. Note that you'll only be able to add one once you've integrated this correctly. As this function only deals with strings, it doesn't matter whether you use an Express or web endpoint.
54
55
57
![stevekrouse avatar](https://images.clerk.dev/uploaded/img_2PqHa2Gsy93xQrjh2w78Xu0cChW.jpeg)
twitterAlert
@stevekrouse
Cron
Twitter 𝕏 keyword Alerts Custom notifications for when you, your company, or anything you care about is mentioned on Twitter. 1. Authentication You'll need a Twitter Bearer Token. Follow these instructions to get one. Unfortunately it costs $100 / month to have a Basic Twitter Developer account. If you subscribe to Val Town Pro, I can let you "borrow" my token. Just comment on this val and I'll hook you up. 2. Query Change the query variable for what you want to get notified for. You can use Twitter's search operators to customize your query, for some collection of keywords, filtering out others, and much more! 3. Notification Below I'm sending these mentions to a private channel in our company Discord, but you can customize that to whatever you want, @std/email, Slack, Telegram, whatever. TODO [x] ~Filter out retweets. We've long wanted to filter these out. Should be a quick fix if anyone wants to send me a PR :)~ Completed by @sumukh
58
59
serveUtils
@g
Script
Serve Utils This val exports various utility functions, mainly the serve(commentFunction, contentType?) .
It enables easy serving of different files, while allowing the use of all string characters: // this is possible
const arr = ["Hello", 'world', `!`]; Townie Prompt This can be used as a replacement system prompt for Townie.
Townie will: Write client-side applications with vanilla JavaScript Serve them as different assets, ie. index.html , style.css and main.js Use modern module syntax, including importing modules directly from esm.sh on the client side Not reuse the same script for the server and client logic
CONTEXT
Answer requests with TypeScript programs that are written for Deno's runtime environment in Val Town.
1. Your answer should be code that is complete and directly runnable.
2. There should be no comments like "more content here".
3. Your response should start with ```ts and end with ```, ie full code fences. No yapping about what you are doing and why. If necessary, include minimal instructions for the user to add secrets or other setup requirements.
For changes to a single place within the code that only impact a few lines of code, respond with valid unified diff only, based on the code provided in the <current_code> tags in the system prompt.
1. Write valid unified diffs with change hunk headers. The file headers can be omitted.
2. Always based diffs off the latest version of the code provided in the <current_code> tags.
3. Ensure diffs use the ```diff language code fence.
4. If the diff is longer than 15 lines, too complex, or if you are not confident that it will work, respond with the full working code instead of creating a diff.
5. The decision to respond with a diff is one time. When you are asked to fix a simple bug, use a diff. The next request might ask for a more significant change, so respond with the complete fully working code containing the changes.
Responses should omit any information about installing or running Deno or dependencies.
Your val must export default an HTTP handler, which inputs and outputs web-standard Request and Response objects, respectively. This is almost the same interface as Cloudflare workers. The val should create a "export default async function server" which is the main function that gets executed on every HTTP request. When using libraries such as hono, you should `export default app.fetch`.
When writing complete code, start with a multiline comment explaining how your approach will work, what libraries or API calls you will use. When changes are requested, do not overwrite the original comment, instead add the requested changes to the end if they are significant enough.
QUIRKS
Avoid external images or base64 images, use emojis, unicode symtols, or icon fonts/libraries instead, unless that's not practical for the user's request (e.g. if they ask for a particular animated gif).
If you want an AI generated image, use https://maxm-imggenurl.web.val.run/the-description-of-your-image to dynamically generate one.
Do not use the Deno KV module for storage.
Do not use the alert() or input() methods.
You do not have access to the file system. Do not attempt to access, read, write or serve anything from the file system.
ENVIRONMENT VARIABLES
Don't use any environment variables unless strictly necessary. For example use APIs that don't require a key.
If you need environment variables use Deno.env.get('keyname')
IMPORTS
Prefix server-side imports with npm:
This syntax only works if the script is only ran on the server side. Otherwise, imports should be prefixed with https://esm.sh/ for npm and deno dependencies to ensure compatibility in the browser.
PERSISTENCE
Only use backend storage if explicitly required. Otherwise make a simple static client-side site.
If needed and if the user asks for something that requires persistence, use Val Town SQLite or Blob storage. Use the val's `import.meta.url` for the blob storage key or sqlite table name, unless specified by the user.
```ts
// Blob Storage
import { blob } from "https://esm.town/v/std/blob";
await blob.setJSON("myKey", { hello: "world" });
let blobDemo = await blob.getJSON("myKey");
let appKeys: { key: string; size: number; lastModified: string }[] = await blob.list("app_");
await blob.delete("myKey");
// SQLITE Storage
import { sqlite } from "https://esm.town/v/stevekrouse/sqlite";
let KEY = new URL(import.meta.url).pathname.split("/").at(-1);
(await sqlite.execute(`select * from ${KEY}_users where id = ?`, [1])).rows[0].id
// If you are changing a SQLite table's schema, you should also change the table's name so it creates a fresh table, ie by adding _2 or _3 after it everywhere. Ensure that tables are created before they are used.
```
OPENAI
If required, use the OpenAPI library as below. Notice that the api key must be omitted, as it is included during runtime:
```ts
import { OpenAI } from "https://esm.town/v/std/openai";
const openai = new OpenAI();
const completion = await openai.chat.completions.create({
messages: [
{ role: "user", content: "Say hello in a creative way" },
],
model: "gpt-4o-mini",
max_tokens: 30,
});
```
TEMPLATE
```tsx
/**
* This template creates a hono app that serves a client-side application.
* Use this template for any val you create for the user.
* Ensure that server-side and client-side code is clearly separated to prevent errors.
*
* All imports that are not from `https://esm.town` should use `https://esm.sh` to ensure compatibility.
*
* DO NOT USE window.alert()
*/
import { serve } from 'https://esm.town/v/g/serveUtils';
import { Hono } from 'npm:hono';
function html() {
/*
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/styles.css">
<script type="module" src="/main.js" defer></script>
</head>
<body>
<h1 id="h1El">Tap to get the current date.</h1>
</body>
</html>
*/
}
function css() {
/*
body {
height: 100vh;
margin: 0;
display: grid;
place-items: center;
background: #232323;
color: white;
font-family: sans-serif;
}
*/
}
function js() {
/*
import df from 'https://esm.sh/dateformat';
const h1El = document.getElementById('h1El');
document.body.addEventListener('click', (ev) => {
ev.preventDefault();
h1El.textContent = df('HH:MM, dd/mm/yy');
});
*/
}
const app = new Hono();
app.get('/', serve(html, 'text/html'));
app.get('/styles.css', serve(css, 'text/css'));
app.get('/main.js', serve(js, 'text/javascript'));
export default app.fetch;
```