Public
Script
  • madhatter349 avatar
    umbrellaReminder
    @madhatter349
    Forked from stevekrouse/umbrellaReminder
    Cron
  • zhanziyang avatar
    dailyDadJoke
    @zhanziyang
    Forked from stevekrouse/dailyDadJoke
    Cron
  • ayush37 avatar
    forwarder
    @ayush37
    Forked from stevekrouse/forwarder
    Email
  • summerboys avatar
    pollRSSFeeds
    @summerboys
    Forked from stevekrouse/pollRSSFeeds
    Cron
  • iampoul avatar
    aqi
    @iampoul
    Forked from stevekrouse/aqi
    Cron
  • natekid avatar
    dailyDadJoke
    @natekid
    Forked from stevekrouse/dailyDadJoke
    Cron
  • nishui avatar
    biliStream
    @nishui
    what is this? ~这是一个用来检测主播是否直播,访问方法为:https://api.val.town/v1/run/nishui.biliStream?args=[xxx]~ ~其中 args=[id] 中的 id 是直播房间号码~ ~现在是多参数 ?args=[[xxx]] ~ 因为不了解 js、TypeScript 语言,决定还是不使用传送过来的参数了,用自定义的列表 id 来每隔 15m 自动获取是否直播,最后打包总结果返回 email 。
    Cron
  • mike968 avatar
    untitled_coffeeElk
    @mike968
    // Sends an email with the joke.
    Cron
  • migmoog avatar
    untitled_oliveLeopon
    @migmoog
    An interactive, runnable TypeScript val by migmoog
    Cron
  • kajgod avatar
    njuskaloCrawl
    @kajgod
    Njuškalo Crawler Crawler for the most popular Croatian eBay-like online store. Allows for several search strings & e-mails if anything new is listed. Also has a password-protected frontend where you can set keywords: https://www.val.town/v/kajgod.njuskaloIndex create a val with only: 'const njuskaloData = {};' fork: Frontend Backend create secret in your profile: njuskalo_password open express endpoint on njuskaloIndex & set cron for njuskaloCrawl to run every hour or 15 min.
    Script
  • ari avatar
    aqi
    @ari
    Forked from stevekrouse/aqi
    Cron
  • cbfrance avatar
    plumZebra
    @cbfrance
    An interactive, runnable TypeScript val by cbfrance
    Cron
  • charlypoly avatar
    valBlogWatcherCron
    @charlypoly
    An interactive, runnable TypeScript val by charlypoly
    Cron
  • samk avatar
    grayLimpet
    @samk
    Forked from stevekrouse/btcPriceAlert
    Cron
  • parkddongddoong avatar
    CS1200
    @parkddongddoong
    // Fetches a random joke.
    Cron
  • petermillspaugh avatar
    emailSubscription
    @petermillspaugh
    Val Town email subscriptions 📧 Handles email subscription signup+verification and sending. Steps Fork and run the sibling Vals to set up SQLite tables: createSubscribers , createNewsletters , createEmailLogs Fork this Val and update for your use case (e.g. confirmation link, sendEmail args, form fields, etc.) Add an HTML form to your frontend that calls /send-verification , or just use / to return a simple HTML form Add a confirmation page on the frontend that calls /confirm-verification Fork sibling Vals to get verification email markup , send verification emails , create a list of newsletters , create a newsletter template , create an individual newsletter , send test emails , send emails , and handle unsubscribe Optionally, fork cousin Vals to view subscribers , email yourself daily subscriber count , email yourself a reminder to write your next newsletter , and send test emails Frontend form You should have a form that hits the /send-verification API endpoint on submit. Remember to adjust the endpoint URL to that of your fork (or else you'll be signing people up for my website!). As a simple alternative, you could use the / handler of this Val, which returns a simple HTML form. Here's a simple example using React: const EmailSignupForm = () => { const [name, setName] = useState(""); const [email, setEmail] = useState(""); async function handleSubmit(e) { e.preventDefault(); setName(""); setEmail(""); const formData = new FormData(); formData.append("name", name); formData.append("email", email); await fetch("https://petermillspaugh-emailSubscription.web.val.run/send-verification", { method: "POST", body: formData, }); } return ( <form onSubmit={handleSubmit}> <label htmlFor="name">First name</label> <input id="name" value={name} onChange={(e) => setName(e.target.value)} type="text" required={true} /> <label htmlFor="email">Email</label> <input id="email" value={email} onChange={(e) => setEmail(e.target.value)} type="email" required={true} /> <button type="submit">Subscribe</button> </form> ); }; You can see a full example on petemillspaugh.com: signup in the footer and code on github . You can add/remove input fields as you wish, of course (e.g. maybe you don't need a name, or maybe you want a how'd-you-hear-about-us field). Just adjust the SQL and frontend implementation accordingly. Frontend confirmation page Create a confirmation page that accepts an email and token as query params and calls the /confirm-verification endpoint. Simple example using React (and Next.js /page directory): const EmailConfirmationPage = () => { const router = useRouter(); const { email, token } = router.query; const [isConfirmed, setIsConfirmed] = useState(false); useEffect(() => { async function confirmEmail() { if (!email || !token) return; const response = await fetch(`https://petermillspaugh-emailSubscription.web.val.run/confirm-verification?email=${email}&token=${token}`, { method: "PUT", }); const { confirmed } = await response.json(); if (confirmed) setIsConfirmed(true); } confirmEmail(); }, [email, token]); if (!isConfirmed) return null; return ( <main> <h1>You’re all set!</h1> </main> ); }; Full example is here and code is here . As an alternative, you could make /confirm-verification a GET route and have your email confirmation link sent by the first route be https://petermillspaugh-emailSubscription.web.val.run/confirm-verification?email=${email}&token=${token} (swapping in your namespace). That would be marginally faster, probably, but you'd still need some way to convey confirmation to the user (e.g. add some "You're all set" message to the return). Plus, the route writes to the subscribers table, so a PUT feels more appropriate. Notes Sending emails to people other than yourself on Val Town is a paid feature—if you want to stay on the free plan, you can go with a package like nodemailer or @sendgrid/mail
    HTTP (deprecated)
July 31, 2024