Newest

☔️ Umbrella reminder if there's rain today

Screenshot 2023-09-14 at 12.31.32.png

Setup

  1. Fork this val 👉 https://val.town/v/stevekrouse.umbrellaReminder/fork
  2. 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

  1. Geocodes an free-form description of a location to latitude and longitude – @stevekrouse.nominatimSearch
  2. Converts a latitude and longitude to weather.gov grid – @stevekrouse.weatherGovGrid
  3. Gets the hourly forecast for that grid
  4. Filters the forecast for periods that are today and >30% chance of rain
  5. If there are any, it formats them appropriately, and sends me an email
Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { email } from "https://esm.town/v/std/email?v=9";
import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON";
import { nominatimSearch } from "https://esm.town/v/stevekrouse/nominatimSearch";
import { weatherGovGrid } from "https://esm.town/v/stevekrouse/weatherGovGrid";
export const umbrellaReminder = async (arg) => {
if (arg.method) return Response.json("");
let location = "prospect heights, brooklyn"; // <---- customize this line
let [{ lat, lon }] = await nominatimSearch({
q: location,
});
let { properties: grid } = await weatherGovGrid({
lat,
lon,
});
let { properties: { periods } } = await fetchJSON(
grid.forecastHourly,
);
let { DateTime } = await import("npm:luxon");
let parse = (iso) => DateTime.fromISO(iso).setZone(grid.timeZone);
let today = periods.filter((x) =>
parse(x.startTime).toLocaleString()
=== DateTime.now().setZone(grid.timeZone).toLocaleString()
);
if (today.every((x) => x.probabilityOfPrecipitation.value < 30))
return today;
let format = (iso) => parse(iso).toFormat("ha").toLowerCase();
let html = `The probabilities of rain in <b>${location}</b> today:<br><br>`
+ today.map((
{ startTime, endTime, probabilityOfPrecipitation: { value: p } },
) => `${format(startTime)}-${format(endTime)}: ${p}%`).join("<br>");
return email({ html, subject: "☔️ Carry an umbrella today!" });
};

#gameplay_agent

This is a val.town mirror of @gameplay/games/agent.

Click the link to see docs.

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* # Agent
*
* This module provides a way to create agents for games.
*
* Agents are http services that get POSTed a game state and return an action.
* If you define your agent with {@link Connect4Agent} or {@link PokerAgent},
* then you can use {@link agentHandler} to create an http service that
* serves it. The service it creates is a standard fetch handler that can be
* used with a variety of different http server libraries.
*
* For Example
*
* ## Deno
*
* ```ts
* import { agentHandler } from "@gameplay/games/agent";
* import { myConnect4Agent } from "./my_connect4_agent.ts";
*
* const handler = agentHandler([
* { game: GameKind.Connect4, agentname: "my-agent", agent: myConnect4Agent },
* ]});
*
* Deno.serve(handler);
* ```
*
* ## Val.Town
*
* ```ts
* import { agentHandler } from "@gameplay/games/agent";
* import { myConnect4Agent } from "./my_connect4_agent.ts";
*
* const handler = agentHandler([
* { game: GameKind.Connect4, agentname: "my-agent", agent: myConnect4Agent },
* ]});
*
* export default handler;
* ```
*
* ## Bun
*
* ```ts
* import { agentHandler } from "@gameplay/games/agent";
* import { myConnect4Agent } from "./my_connect4_agent.ts";
*
* const handler = agentHandler([
* { game: GameKind.Connect4, agentname: "my-agent", agent: myConnect4Agent },
* ]});
*
* Bun.serve({fetch: handler});
* ```
*
* More than one agent can be registered so you can have multiple agents served
* by the same http service.
*
* You must host your own agent service and make sure it's publically
* accessible. You could use a service like Vercel, Cloudflare Workers, or
* Deno Deploy. The best and easiest way to host your agent service is to use
* val.town.
*
* You can also write your own agent service that implements the same http
* interface as {@link agentHandler}. This means you can use python or go or any
* other language to write your agent service, but you don't get the benefit of
* having all the game logic that you do by writing your agent in javascript or
* typescript and using this library.
*
* @module
*/
import type { Connect4Agent, Connect4AsyncAgent } from "https://esm.town/v/saolsen/gameplay_connect4";
import type { GameKind, Json } from "https://esm.town/v/saolsen/gameplay_games";
import type { PokerAgent, PokerAsyncAgent } from "https://esm.town/v/saolsen/gameplay_poker";
/**
* A Connect4 Agent
*
* @template T The type of the agent data.
* * Must extend {@link Json} which restricts it to a JSON serializable type.
*/
export interface Connect4AgentSpec<
T extends Json = Json,
> {
game: GameKind.Connect4;
/** The name of the agent. */
agentname: string;
/** The agent function. */
agent: Connect4Agent<T> | Connect4AsyncAgent<T>;
}
/**
* A Poker Agent
*
* @template T The type of the agent data.
* * Must extend {@link Json} which restricts it to a JSON serializable type.*
*/
export interface PokerAgentSpec<
T extends Json = Json,
> {
game: GameKind.Poker;
/** The name of the agent. */
agentname: string;

Quill.js WYSIWYG

Basic WYSIWYG rich text editor, using quill.js

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
export default async function(req: Request) {
if (req.method === "POST") {
const name = (await req.formData()).get("name");
return new Response("Hello World");
}
return new Response(
`<html>
<head>
<title>Title</title>
<style>{"html { font-family: sans-serif; }"}</style>
<script src="https://unpkg.com/htmx.org@1.9.9"></script>
<script>htmx.logAll()</script>
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.core.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.snow.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.js"></script>
</head>
<body>
<div id="editor" hx-on:click="console.log(quill.getSemanticHTML())">
<div id="editor-container"></div>
<p>Hello World!</p>
<p>
Some initial <strong>bold</strong> text
</p>
<p>
<br />
</p>
</div>
<script>
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
['link', 'image', 'video', 'formula'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered'}, { 'list': 'bullet' }, { 'list': 'check' }],
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'font': [] }],
[{ 'align': [] }],
['clean'] // remove formatting button
];
let options = {
debug: 'info',
modules: {
toolbar: toolbarOptions,
},
theme: 'snow',
};
let quill = new Quill('#editor', options)
const container = quill.addContainer('ql-custom');
</script>
</body>
</html>`,
{
headers: {
"Content-Type": "text/html; charset=utf-8",
},
},
);
}

A minimal bookmarking tool

This allows you to bookmark links and view them later. Completely powered by ValTown and SQLite.

To set this up for yourself

  1. Fork the val
  2. From your ValTown settings page, add an environment variable named bookmarks_client_id and give it a value (you will be using this for saving)
  3. Add another environment variable named bookmarks_client_secret and give it a value (you will also be using this for saving)
  4. At first, the "bookmarks" table will not exist, so we need to save an article first, which will create the "bookmarks" table
  5. To do this, add a bookmarklet to your browser with this value (replace BOOKMARKS-CLIENT-ID and BOOKMARKS-CLIENT-SECRET with the values you added to the environment variables, and replace BOOKMARKS-URL with your VAL's URL):
javascript:void(open('BOOKMARKS-URL/save?u='+encodeURIComponent(location.href)+'&t='+encodeURIComponent(document.title)+'&id=BOOKMARKS-CLIENT-ID&secret=BOOKMARKS-CLIENT-SECRET', 'Bookmark a link', 'width=400,height=450'))
  1. Click this bookmarklet to bookmark the URL of the current active tab
  2. Go to your VAL URL homepage to see the bookmark

Demo

Here are my bookmarks: https://ramkarthik-bookmark.web.val.run/

Note

Make sure you don't share bookmarks_client_id and bookmarks_client_secret. It is used for authentication before saving a bookmark.

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { sqlite } from "https://esm.town/v/std/sqlite?v=4";
import { Hono } from "npm:hono@3";
const app = new Hono();
app.get("/", async (c) => {
var page = parseInt(c.req.query("page") || "0");
var offset = 0;
if (page && page > 0) {
offset = page * 10;
}
var bookmarks = await sqlite.execute({
sql: "select title, url from bookmarks order by created_at desc limit 10 offset :offset",
args: { offset: offset },
});
var totalBookmarkRows = await sqlite.execute("select count(1) from bookmarks order by created_at desc");
var totalBookmarks = parseInt(totalBookmarkRows.rows[0][0].toString());
var pagesCount = Math.floor(
((totalBookmarks % 10) == 0 && totalBookmarks / 10 > 0)
? ((totalBookmarks / 10) - 1)
: (totalBookmarks / 10),
);
var bookmarksList = "";
for (var i = 0; i < bookmarks.rows.length; i++) {
bookmarksList += "<p>" + (page * 10 + i + 1) + ". <a href=\"" + bookmarks.rows[i][1] + "\">" + bookmarks.rows[i][0]
+ "</a></p>";
}
var pagination = "<div style=\"flex-direction: row; width: 100%;justify-content: space-between;\">";
if (page > 0) {
pagination += "<a href=\"?page=" + (page - 1) + "\"> < prev </a>";
}
if (page < pagesCount) {
pagination += "<a href=\"?page=" + (page + 1) + "\"> next > </a>";
}
pagination += "</div>";
const html = `<html>
<head>
<title>My reading list</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
</head>
<body style="width:70%; margin-left:15%">
<h1>Reading list</h1>`
+ bookmarksList
+ pagination + `</body>
</html>`;
return new Response(
html,
{
headers: {
"Content-Type": "text/html",
},
},
);
});
app.get("/save", async (c) => {
const id = c.req.query("id");
const secret = c.req.query("secret");
const title = c.req.query("t");
const url = c.req.query("u");
if (!id && !secret) {
return c.text("Authentication details (ID/Secret) missing!");
}
if (id != Deno.env.get("bookmarks_client_id") || secret != Deno.env.get("bookmarks_client_secret")) {
return c.text("Unauthorized!");
}
if (!url) {
return c.text("URL missing!");
}
const create_table = await sqlite.execute(
"CREATE TABLE IF NOT EXISTS bookmarks (title TEXT, url TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP)",
);
const res = await sqlite.execute({
sql: `insert into bookmarks (title, url) values (:title, :url)`,
args: { title: title, url: url },
});
return c.text("Saved!");
});
export default app.fetch;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/** @jsxImportSource https://esm.sh/preact */
import { render } from "npm:preact-render-to-string";
// import Quill from "npm:quill";
export default async function(req: Request) {
if (req.method === "POST") {
const name = (await req.formData()).get("name");
return new Response(render(<>Hello {name || "World"}!</>));
}
return new Response(
render(
<html>
<head>
<title>Title</title>
<style>{"html { font-family: sans-serif; }"}</style>
<script src="https://unpkg.com/htmx.org@1.9.9"></script>
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.core.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.core.js"></script>
</head>
<body>
<div id="editor" hx-on:load='let quill = new Quill("#editor")'>
<p>Hello World!</p>
<p>
Some initial <strong>bold</strong> text
</p>
<p>
<br />
</p>
</div>
</body>
</html>,
),
{
headers: {
"Content-Type": "text/html; charset=utf-8",
},
},
);
}

A val to list other vals, very meta!

Until folder sharing is supported, this may be the best way to point to specific vals?

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo";
import { html } from "https://esm.town/v/pomdtr/gfm";
import { readme } from "https://esm.town/v/pomdtr/readme";
const vals = await Promise.all(
[
"mxdvl/haversine_distance",
"mxdvl/cities",
"mxdvl/trips",
"mxdvl/round",
"mxdvl/vals",
]
.map(url => extractValInfo(`https://val.town/v/${url}`))
.map(async ({ author, name, embedUrl }) => ({ embedUrl, readme: await readme(author, name) })),
);
const css = `
body { font-family: system-ui; }
ul { list-style-type: none; padding: 0; }
li { background: aliceblue; padding: 0.5em; border-radius: 0.25em; }
li:not(:last-child) { margin-block: 1rem; }
iframe { border: none; height: 12rem; width: 100% }`;
export default async function(req: Request) {
return new Response(
`
<html>
<head>
<title>Vals of interest</title>
<style>${css}</style>
</head>
<body>
<h1>
Vals of interest
</h1>
<ul>
${
vals.map(({ embedUrl, readme }) => (
`<li>
${html(readme)}
<iframe src="${embedUrl}"></iframe>
</li>`
)).join("\n")
}
</ul>
</body>
</html>`,
{
headers: {
"Content-Type": "text/html; charset=utf-8",
},
},
);
}
1
export { default } from "https://esm.town/v/nbbaier/sqliteExplorerApp?v=81";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo?v=26";
import { openKv } from "https://esm.town/v/pomdtr/kv?v=3";
import { sqlite } from "https://esm.town/v/std/sqlite?v=6";
import { DenoSyntheticKV } from "https://esm.town/v/stevekrouse/DenoSyntheticKV?v=10";
import { createStore, sqliteStore } from "https://esm.town/v/vladimyr/keyvhqSqlite";
import Keyv from "npm:@keyvhq/core";
type TestObj = { test: number };
// setup openKv
const kv1 = openKv<TestObj>();
// setup Keyv
const { slug: namespace } = extractValInfo(import.meta.url);
// const store = sqliteStore; /* same as: const store = createStore({ table: "keyv" }); */
const store = createStore({ table: "keyv" });
const kv2 = new Keyv<TestObj>({ namespace, store });
// setup DenoSyntheticKV
const kv3 = new DenoSyntheticKV("keyv");
await kv1.set("foo", { test: 42 });
console.log("@std/sqlite:", (await sqlite.execute("select * from keyv")).rows);
console.log("openKv:", await kv1.get("foo"));
console.log("Keyv:", await kv2.get("foo"));
// doesn't work because DenoSyntheticKV serializes key to {"json":"vladimyr/kv_example:foo"}
console.log("DenoSyntheticKV:", await kv3.get(`${namespace}:foo`));
let data = await kv2.get("foo");
data.test += 1;
await kv2.set("foo", data);
console.log("\n@std/sqlite:", (await sqlite.execute("select * from keyv")).rows);
console.log("openKv:", await kv1.get("foo"));
console.log("Keyv:", await kv2.get("foo"));
// doesn't work because DenoSyntheticKV serializes key to {"json":"vladimyr/kv_example:foo"}
console.log("DenoSyntheticKV:", await kv3.get(`${namespace}:foo`));

Create your own Myspace profile, deployed to Val town. https://jdan-myspace.web.val.run

Screenshot 2024-04-27 at 7.20.32 PM.png

Click "..." and select Fork to create your own.

Screenshot 2024-04-27 at 7.18.00 PM.png

From there you can:

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { myspaceHtml } from "https://esm.town/v/jdan/myspaceHtml";
import { Hono } from "npm:hono@3";
// TODO: Fetch from key-value
const profile = {
displayName: "Jordan",
seo: {
title: "Jordan Scales | Myspace.com",
},
info: {
imageUrl: "https://jordanscales.com/me.png",
allImagesUrl: "https://instagram.com/jdanscales",
status:
`<span style="color:purple"><em>~*~ do you realize<br>I could have been the one to change your life? - xcx ~*~</em></span>`,
gender: "Male",
age: 31,
location: ["Hoboken, NEW JERSEY", "United States"],
lastLogin: "04/27/2024",
},
contact: {
sendMessage: "mailto:hello@example.com",
forwardToFriend: "https://twitter.com/intent/tweet?url=https%3A%2F%2Fjordanscales.com",
addToFriends: "https://twitter.com/jdan",
addToFavorites: "https://www.val.town/v/jdan/myspace",
},
interests: {
general: "Reading, surfing the web, video games, long walks with friends, bubble tea, programming, chess, art",
music:
"LIGHTS, Daft Punk, Mr. Oizo, The Chemical Brothers, CHVRCHES, Japanese Breakfast, The Prodigy, PVRIS, The Japanese House, Poppy, blink-182, Chrome Sparks, Ashnikko, Rezz, Grimes, Bag Raiders, Kim Petras, Tegan and Sara, Charli XCX, MARINA",
television: " Boardwalk Empire, The Sopranos, The Office, Parks and Recreation, King of Queens, See, Crashing",
books:
"Three Body Problem (Remembrance of Earth's Past trilogy), Alex's Adventures in Numberland, Things to Make and Do in the Fourth Dimension, Ball Lightning",
},
details: {
status: "Single",
hereFor: "Dating, Serious Relationships, Friends, Networking",
hometown: "Middletown, NJ",
sign: "Cancer",
smokeDrink: "No / Sometimes",
occupation: "Webmaster",
},
schools: [
{
details: [
"Stevens Institute of Technology",
"Hoboken, NEW JERSEY",
"Degree: Bachelor's Degree",
"Major: Computer Science",
"Minor: Mathematics, Science and Technology Studies",
],
start: "2010",
end: "2014",
},
{
details: [
"Middletown High School South",
"Middletown, NEW JERSEY",
"President: Computer Club",
],
start: "2006",
end: "2010",
},
],
links: [
{ url: "https://twitter.com/jdan", text: "Twitter" },
{ url: "https://mastodon.xyz/@jordan", text: "Mastodon" },
{ url: "https://github.com/jdan", text: "GitHub" },
{ url: "https://notes.jordanscales.com/", text: "Blog" },
{ url: "https://hash.jordanscales.com/", text: "Hashart" },
],
blog: {
allPostsUrl: "https://notes.jordanscales.com",
posts: [
{
title: "Is this true?",
url: "https://notes.jordanscales.com/is-this-true",
},
{
title: "Operating on Infinite Lists",
url: "https://notes.jordanscales.com/infinite-lists",
},
{
title: "I Peeked Into My Node_Modules Directory And You Won’t Believe What Happened Next",
url: "https://notes.jordanscales.com/node_modules",
},
],
},
blurbs: {
aboutMe:
`My name is Jordan and I'm not sure what to put on my new profile. I'm a software developer based out of Hoboken, New Jersey and I like to
build things that make people smile.<br><br>
I'm currently trying to get better at <a href="https://lichess.org/@/jordanscales">chess</a> and occasionally making
<a href="https://hash.jordanscales.com/">some art</a>.<br><br>
I write the most words on twitter (<a href="https://twitter.com/jdan">@jdan</a>) and <a href="https://notes.jordanscales.com">my blog</a>.<br><br>
`,
whoIdLikeToMeet: "Tom! Thank you for making the Internet truly good for a while. but most of all, Samy is my hero",
},
top8: {

Create your own Myspace profile, deployed to Val town. https://jdan-myspace.web.val.run

Screenshot 2024-04-27 at 7.20.32 PM.png

Click "..." and select Fork to create your own.

Screenshot 2024-04-27 at 7.18.00 PM.png

From there you can:

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { myspaceHtml } from "https://esm.town/v/jdan/myspaceHtml";
import { Hono } from "npm:hono@3";
// TODO: Fetch from key-value
const profile = {
displayName: "Jordan",
seo: {
title: "Jordan Scales | Myspace.com",
},
info: {
imageUrl: "https://jordanscales.com/me.png",
allImagesUrl: "https://instagram.com/jdanscales",
status:
`<span style="color:purple"><em>~*~ do you realize<br>I could have been the one to change your life? - xcx ~*~</em></span>`,
gender: "Male",
age: 31,
location: ["Hoboken, NEW JERSEY", "United States"],
lastLogin: "04/27/2024",
},
contact: {
sendMessage: "mailto:hello@example.com",
forwardToFriend: "https://twitter.com/intent/tweet?url=https%3A%2F%2Fjordanscales.com",
addToFriends: "https://twitter.com/jdan",
addToFavorites: "https://www.val.town/v/jdan/myspace",
},
interests: {
general: "Reading, surfing the web, video games, long walks with friends, bubble tea, programming, chess, art",
music:
"LIGHTS, Daft Punk, Mr. Oizo, The Chemical Brothers, CHVRCHES, Japanese Breakfast, The Prodigy, PVRIS, The Japanese House, Poppy, blink-182, Chrome Sparks, Ashnikko, Rezz, Grimes, Bag Raiders, Kim Petras, Tegan and Sara, Charli XCX, MARINA",
television: " Boardwalk Empire, The Sopranos, The Office, Parks and Recreation, King of Queens, See, Crashing",
books:
"Three Body Problem (Remembrance of Earth's Past trilogy), Alex's Adventures in Numberland, Things to Make and Do in the Fourth Dimension, Ball Lightning",
},
details: {
status: "Single",
hereFor: "Dating, Serious Relationships, Friends, Networking",
hometown: "Middletown, NJ",
sign: "Cancer",
smokeDrink: "No / Sometimes",
occupation: "Webmaster",
},
schools: [
{
details: [
"Stevens Institute of Technology",
"Hoboken, NEW JERSEY",
"Degree: Bachelor's Degree",
"Major: Computer Science",
"Minor: Mathematics, Science and Technology Studies",
],
start: "2010",
end: "2014",
},
{
details: [
"Middletown High School South",
"Middletown, NEW JERSEY",
"President: Computer Club",
],
start: "2006",
end: "2010",
},
],
links: [
{ url: "https://twitter.com/jdan", text: "Twitter" },
{ url: "https://mastodon.xyz/@jordan", text: "Mastodon" },
{ url: "https://github.com/jdan", text: "GitHub" },
{ url: "https://notes.jordanscales.com/", text: "Blog" },
{ url: "https://hash.jordanscales.com/", text: "Hashart" },
],
blog: {
allPostsUrl: "https://notes.jordanscales.com",
posts: [
{
title: "Is this true?",
url: "https://notes.jordanscales.com/is-this-true",
},
{
title: "Operating on Infinite Lists",
url: "https://notes.jordanscales.com/infinite-lists",
},
{
title: "I Peeked Into My Node_Modules Directory And You Won’t Believe What Happened Next",
url: "https://notes.jordanscales.com/node_modules",
},
],
},
blurbs: {
aboutMe:
`My name is Jordan and I'm not sure what to put on my new profile. I'm a software developer based out of Hoboken, New Jersey and I like to
build things that make people smile.<br><br>
I'm currently trying to get better at <a href="https://lichess.org/@/jordanscales">chess</a> and occasionally making
<a href="https://hash.jordanscales.com/">some art</a>.<br><br>
I write the most words on twitter (<a href="https://twitter.com/jdan">@jdan</a>) and <a href="https://notes.jordanscales.com">my blog</a>.<br><br>
`,
whoIdLikeToMeet: "Tom! Thank you for making the Internet truly good for a while. but most of all, Samy is my hero",
},
top8: {