/targetblank

organize your links

Primary LanguageTypeScriptMIT LicenseMIT


  • Productivity focused   Do everything from the comfort of your keyboard.

  • Shareable   Pages are publicly readable by anyone with the link.

  • Optimized for performance   Aggressive caching, small code bundles and native font stacks.

  • Browser Extension Packaged as an extension to replace your homepage (firefox, chrome).

Document Format

The page structure is defined entirely by the document. Instead of adding, updating and removing links with buttons, targetblank uses text to represent your page. Although the syntax is completely different, it works similarly to other structured documents like markdown or yaml.

A minimal document contains at least a version line and a header line. The version is the first thing the parser reads, and it makes it easier to keep the format backwards-compatible if the syntax needs to change in the future.

+ version 1
+ ===

The space between the version and header lines is used for metadata about the page. For now, this only allows the page's title to be configured, but please open an issue to share your ideas (ex. background image). The format of a metadata entry is a name, followed by = and finally the value.

  version 1
+ title = Hello World!
  ===

Your links are added after the header line and can be formatted in two ways. The simplest way is to simply write the link on its own line, the parser will make sure it's detected and clickable. Alternatively, links can be labelled, which lets you control what text is displayed in place of the full link.

  version 1
  title = Hello World
  ===
+ example.com?q=foo
+ labelled link [example.com?q=bar]

You can also add labels on their own, without a link. These will not be clickable, but can be a convenient way to organize your links. For even more control, the links and labels can be indented into whatever shape makes sense for your use case.

  version 1
  title = Hello World
  ===
+ productivity
      example.com?q=foo
+         example.com/baz
      labelled link [example.com?q=bar]

When a single group isn't enough, you can add a group delimiter to create a new one and add more links. This will be reflected on the homepage by a new section side-by-side with the first one. After a few groups (depending on the size of your screen) they will start wrapping underneath the first row of sections on the homepage.

  version 1
  title = Hello World
  ===
  productivity
      example.com?q=foo
          example.com/baz
      labelled link [example.com?q=bar]
  ---
+ communication
+     example.com/chat

Keyboard Shortcuts

Targetblank is meant to be usable and productive using only a keyboard. The document format goes a long way towards making that a reality, but these shortcuts help complete the story, adding quick navigation and useful text-editing commands. The editor shortcuts are inspired by common text editor keybindings and work on multi-line selections. If your favorite shortcut is missing, please let me know.

Page Shortcut Keys
Homepage Open editor shift + e
  Search links <any letters>
  Follow link enter
Editor Close editor esc
  Indent tab
    ctrl + ]
  Un-indent shift + tab
    ctrl + [
  Move up alt + up
  Move down alt + down
  Toggle comment ctrl + /

Development

Build Status Test Coverage

$ npm run dev

This will launch a local server which watches and serves contents from ./website.

The api is not mocked in dev mode, it points to production endpoints.

Testing

$ go test ./...

Tests all backend packages (routing, handler logic and document parsing).

$ npm run test

Checks code quality, runs unit tests on helpers and builds the bundle.

Extension

Developing the extension starts the same as usual website development.

$ npm run build:extension

Chrome: navigate to chrome://extensions, enable developer mode, and load unpacked from the .extension directory.

Firefox: navigate to about:debugging#/runtime/this-firefox, and load temporary add-on from any file in the .extension directory.

You will need to open a new tab to view the most recent version of the extension (no hot-reload).

Sourcing the extension contents from .website will use the actual bundle, but will not be updated on save.

Deployment

This project is hosted on AWS and uses Terraform to manage the cloud resources.

The deployment workflow uses GitHub Actions to package and apply changes on every change to master.

Deployment to the extension stores runs in the same deployment pipeline as the website. New versions will only be published when the manifest's version changes.

API

The API is rooted at https://api.targetblank.org. Details about arguments and return values can be found by following the links to the function implementations.

The addr path parameter represents the six character string which identifies a page.

Function Description Method Path
authenticate Create authentication token POST /auth/:addr
passwd * Update page password PUT /auth/:addr
reset Request page password reset DELETE /auth/:addr
create Create new page POST /page
read ** Fetch page content GET /page/:addr
update * Edit page document PUT /page/:addr
validate Validate page document POST /page/validate

* Authentication required.

** Authentication may be required depending on page configuration.

Schema

All data is stored in a single page table. Each item represents both a single page and its owner.

Attribute Raw Type Description
addr string Page address (key)
document string Parsed document stored as JSON
email string Hashed page email
password string Hashed page password
password_last_update string Timestamp of when the password was last updated
published bool Published pages are readable without authentication

License

MIT