crif-bookmark.web.val.run
Readme

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.

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 href=\"/edit\">edit</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;
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
v2
April 23, 2024