15## How to use this Val
16
17🔑 **Important** https://apiflash.com free key required for generating screenshots. (Will update with option to generate on device)
18
19This Val is separated into 2 directories, the `api/` and the `frames/`.
20Take a look at each frame to see an example of what will be displayed on your e-ink display.
21
22The `api/` directory holds endpoints for each Val. These endpoints could be used across projects
23and will soon be moved to their own. Each one is cached server side (on val.town) to reduce traffic to free/public apis.
24
25Remixes and pull requests welcome!
2import React from "https://esm.sh/react";
3import { renderToString } from "https://esm.sh/react-dom/server";
4import GetWeather, { type WEATHER_FORECAST } from "../api/weather.ts";
5import { BodyWrapper, Content, Footer, Header, Headline } from "../components.tsx";
6
34 const url = new URL(req.url);
35
36 const apiUrl =
37 `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t_weather=true&temperature_unit=fahrenheit`;
38 const cacheKey = `weather-forecast-${latitude}-${longitude}`;
39
40 // Cache for 30 minutes
41 const data: WEATHER_FORECAST = await fetchWithCache(apiUrl, cacheKey, 30).then((res) => res.json());
42 return new Response(JSON.stringify(data), {
43 headers: {
2import React from "https://esm.sh/react";
3import { renderToString } from "https://esm.sh/react-dom/server/";
4import GetNews from "../api/news.ts";
5import { BodyWrapper, Content, Footer, Header, Headline } from "../components.tsx";
6
7// REQUIRES API KEY - see api/news.ts
8function Render({ news }: { news: Record<string, any> }) {
9 const line = "To be taught if fortunate";
1import fetchWithCache from "./fetchWithCache.ts";
2
3const GUARDIAN_API_KEY = Deno.env.get("GUARDIAN_API_KEY");
4
5export default async function(req: Request): Promise<Response> {
21 };
22
23 const address = `https://content.guardianapis.com/search?api-key=${GUARDIAN_API_KEY}&page-size=${size}`;
24 const apiUrl = address + `&${new URLSearchParams(searchParameters).toString()}`;
25 const cacheKey = `guardian_headlines_${size}`;
26
27 const data = await fetchWithCache(apiUrl, cacheKey).then((res) => res.json());
28 return new Response(JSON.stringify(data), {
29 headers: {
2import React from "https://esm.sh/react";
3import { renderToString } from "https://esm.sh/react-dom/server";
4import GetLogs, { type HEMOLOG_TREATMENT } from "../api/hemolog.ts";
5import { BodyWrapper, Content, Footer, Header, Headline } from "../components.tsx";
6
19 const url = new URL(req.url);
20
21 const apiUrl = "https://hemolog.com/api/recent-treatments?alertid=mike29";
22 const cacheKey = "hemolog-recent-treatments";
23
24 const data: HEMOLOG_TREATMENT[] = await fetchWithCache(apiUrl, cacheKey).then((res) => res.json());
25 return new Response(JSON.stringify(data), {
26 headers: {
1// Generates a screenshot using APIFlash.com from a url
2// API key required
3
4// TODO: Add caching of image
11 return new Response("No url provided", { status: 500 });
12 }
13 const apiKey = Deno.env.get("API_FLASH_KEY");
14 const generateUrl =
15 `https://api.apiflash.com/v1/urltoimage?access_key=${apiKey}&url=${valUrl}&width=${width}&height=${height}&format=png&fresh=true`;
16
17 try {
18 const response = await fetch(generateUrl);
19 if (!response.ok) {
20 throw new Error(`APIFlash responded with status: ${response.status}`);
21 }
22 return response;
7
8export default async function fetchWithCache(
9 apiUrl: string,
10 cacheKey: string,
11 cacheMinutes: number = 10,
38
39 // Fetch new data if no valid cache exists
40 const response = await fetch(apiUrl);
41 if (!response.ok) {
42 throw new Error(`API responded with status: ${response.status}`);
43 }
44 const data = await response.json();
9 <meta charSet="UTF-8" />
10 <title>{title}</title>
11 <link rel="preconnect" href="https://fonts.googleapis.com" />
12 {/* Getting a type error here */}
13 {/* <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> */}
14 <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet" />
15 <link href="https://fonts.googleapis.com/css2?family=Doto:wght@100..900&display=swap" rel="stylesheet" />
16 <link href="https://fonts.googleapis.com/css2?family=Rancho&display=swap" rel="stylesheet" />
17 <link href="https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap" rel="stylesheet" />
18 <link
19 href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap"
20 rel="stylesheet"
21 />