Coder Social home page Coder Social logo

silverbulletmd / silverbullet Goto Github PK

View Code? Open in Web Editor NEW
1.9K 14.0 129.0 32.52 MB

The hackable notebook

Home Page: https://silverbullet.md

License: MIT License

TypeScript 94.29% HTML 0.45% JavaScript 0.43% SCSS 3.76% Makefile 0.01% Shell 0.75% Dockerfile 0.18% CSS 0.13%
knowledge-management markdown personal-knowledge-management note-taking end-user-programming

silverbullet's Introduction

SilverBullet

SilverBullet is a note-taking application optimized for people with a hacker mindset. We all take notes. There’s a million note taking applications out there. Literally. Wouldn’t it be nice to have one where your notes are more than plain text files? Where your notes essentially become a database that you can query; that you can build custom knowledge applications on top of? A hackable notebook, if you will?

This is what SilverBullet aims to be.

Absolutely. You use SilverBullet to quickly jot things down. It’s a notes app after all. However, this is just the beginning. Gradually, you start to annotate your notes using Frontmatter. You realize: “Hey, this note represents a person, let me tag it as such.” Before you know it, you’re turning your notes into Objects. Then you learn that in SilverBullet you can Live Query these objects. Your queries grow into reusable Templates written using a powerful Template Language. You find more and more uses of these templates, for instance to create new pages, or widgets automatically added to your pages.

And then, before you know it — you realize you’re effectively building applications in your notes app. End-User Programming, y’all. It’s cool.

You may have been told there is no such thing as a silver bullet.

You were told wrong.

Introduction to SilverBullet

Features

SilverBullet...

  • Runs in any modern browser (including on mobile) as a PWA in two Client Modes (online and synced mode), where the synced mode enables 100% offline operation, keeping a copy of content in the browser, syncing back to the server when a network connection is available.
  • Provides an enjoyable markdown writing experience with a clean UI, rendering text using Live Preview, further reducing visual noise while still providing direct access to the underlying markdown syntax.
  • Supports wiki-style page linking using the [[page link]] syntax. Incoming links are indexed and appear as “Linked Mentions” at the bottom of the pages linked to thereby providing bi-directional linking.
  • Optimized for keyboard-based operation:
    • Quickly navigate between pages using the page switcher (triggered with Cmd-k on Mac or Ctrl-k on Linux and Windows).
    • Run commands via their keyboard shortcuts or the command palette (triggered with Cmd-/ or Ctrl-/ on Linux and Windows).
    • Use Slash Commands to perform common text editing operations.
  • Provides a platform for end-user programming through its support for Objects, Live Queries and Live Templates.
  • Robust extension mechanism using plugs.
  • Self-hosted: you own your data. All content is stored as plain files in a folder on disk. Back up, sync, edit, publish, script with any additional tools you like.
  • SilverBullet is open source, MIT licensed software.

Installing SilverBullet

Check out the instructions.

Developing SilverBullet

Open in Gitpod

SilverBullet is written in TypeScript and built on top of the excellent CodeMirror 6 editor component. Additional UI is built using Preact. ESBuild is used to build both the front-end and back-end bundles. The server backend runs as a HTTP server on Deno using and is written using Oak.

To prepare the initial web and plug build run:

deno task build

To symlink silverbullet to your locally checked-out version, run:

deno task install

You can then run the server in “watch mode” (automatically restarting when you change source files) with:

deno task watch-server <PATH-TO-YOUR-SPACE>

After this initial build, it's convenient to run three commands in parallel (in separate terminals):

deno task watch-web
deno task watch-server <PATH-TO-YOUR-SPACE>
deno task watch-plugs

To typecheck the entire codebase (recommended before submitting PR):

deno task check

To run unit tests:

deno task test

Feedback

If you (hypothetically) find bugs or have feature requests, post them in our issue tracker. Would you like to contribute? Check out the code, and the issue tracker as well for ideas on what to work on. Also be sure to check out our Discourse community.

silverbullet's People

Contributors

ahmednreldin avatar chriszarate avatar daniel-michel avatar ekaragodin avatar gorootde avatar hanzei avatar ishehadeh avatar jim-fx avatar jimt avatar joekrill avatar johnlunney avatar jordanpaoletti avatar justyns avatar kjk avatar m1lt0n avatar maarrk avatar maks-s avatar onespaceman avatar patrikstenmark avatar pinjasaur avatar prcrst avatar rjgibson avatar siddhant3s avatar sinansonmez avatar sweisgerber avatar tmichela avatar tristansokol avatar v411e avatar willyfrog avatar zefhemel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

silverbullet's Issues

Theming support

Currently all styles are hard-coded in various SCSS files, we probably will want a theming system.

Plenty of design decisions to be made here:

  • Should themes be defined in plain CSS or e.g. JSON? We’d want to be able to hot load and unload these and likely namespace them somehow.
  • Should themes be plugs, part of plug YAML definitions maybe even, or be something completely different?
  • CodeMirror has its own theming mechanism should we leverage this somehow?
  • Custom syntax in plug YAML can define styling as well, such as colors. How would this interact with themes?

Modal syscall

We currently have LHS, RHS and BHS panels you can show and hide. I think for certain use case a (close to) full screen modal panel may be useful as well. For instance to implement a plug to create a configuration screen, or some other type of UI.

validate plug yaml

yaml is very flexible, and sometimes that allows for creating some typos that might not be caught until hours later of dimissing any other possible cause.

having a yaml validator that issues a warning (we should keep the flexibility) when building a plug, would probably help figuring out some of this problems beforehand.

In my specific case my yaml was like:

name: mattermost
functions:
  postUnfurlOptions:
    path: ./channels.ts:unfurlOptions
    event: unfurl:options
  postUnfurl:
    path: ./channels.ts:unfurl
    event: unfurl:mattermost-unfurl

which caused the unfurl event to not dispatch and later on it didn't apply the function (yes, I failed twice on the same spot 🤦🏼 )

having some basic structure validation on build, could have prevented that on the first attempt to build it.

Documentation: #template and #include

Fully undocumented and not even demoed feature:

<!-- #template "templates/my-template" {"json-key": "hello"} -->

<!-- /template -->

Similar to queries in that it replaces its body on the fly (ish), but replaces it with a (handlebars) template instead optionally with a JSON object as its root. #include does the same, but doesn't accept the JSON object and just includes the template verbatim. The template path can also be a URL, see: https://github.com/silverbulletmd/silverbullet/blob/main/website/%F0%9F%94%8C%20Ghost.md?plain=1#L7

Attachment management

As of #71 attachments are implemented. You can copy & past, or drag & drop files into a page, and they will be uploaded and linked. There are a few things missing:

  • Delete attachments (inside of SB, you can just delete files outside of SB as you like, of course)
  • Attachment indexing (tracking which page reference what attachment). Currently all attachments are linked either via [text](attachment/PATH) or ![text](attachment/PATH) so indexing based on this should work. Indexing would allow e.g. renaming of attachments or give warnings (or remove references) when to-be-deleted-attachments are about to be deleted.

Plug for Mattermost

It would be useful to have an integration with Mattermost in SB.

Ideas for Channels:

  • "saved posts" as a query provider, perhaps and perhaps providing a command that unsaved a post so you can use it as a task list
  • "recent mentions" as a query provider

Ideas for Boards:

  • Expose a board's list of cards as a query provider

Other ideas?

Bad link behaviour

I'm not sure what the right behaviour should be, but if you have a badly formatted link like:

[badlink]()

this will take you to:
https://yourserver/) (notice the ))

as I said, the link is not right as it doesn't contain any url, but opening to that seems weird. Maybe not linking or link to the same page would be more appropriate...

Read-only mode (for mobile only?)

When I use SB on mobile (with on-screen keyboard) I often get annoyed by the keyboard popping up when I just want to read some stuff. I’m now considering if we should add a simple read/edit mode button in the top-right bar only visible for mobile devices. Double tapping a page in read mode would also switch it to edit mode.

At a technical level this is pretty easy to do, SB already has a read-only mode but it’s only used in very few places (like for full-text search results).

Visual indication that saving a page failed

Currently if saving a not fails it does so quietly, that's pretty bad. There should at least be a flashNotification about this, but ideally it shows the page title in red in this case.

Mattermost plugin build instructions

Hello team,

I have tried to build mattermost plugin via make command but it seems some files were not committed to the repo.
I see lines like include build/setup.mk in make file but do not see this folder.

anything I'm missing? Thank you.

Backlinks in the RHS

It may be helpful to have a mode where the RHS (right-hand side) always shows backlinks to the current page. These are already indexed into a database, so it’s primarily a matter of rendering them in the RHS (and having those links properly work).

Implementation note: this can be done very similarly to how Markdown preview is implemented, likely including how internal links are made to work there (a bit of a hack with target=“_top”).

Keep space settings in `SETTINGS` page

Similar to the “built-in” PLUGS page, we can also have a SETTINGS page in which we keep a YAML block with various space-specific settings.

Examples could include:

  • A configurable prefix for page templates for the “instantiate page template” command (currently hardcoded)
  • A configurable prefix for the snippet command (currently hardcoded)
  • Any other plug-specific settings plugs may need (perhaps nested, e.g. a “ghost” top-level key, with more ghost-specific settings nested under it)

Example SETTINGS page:

  This is your SETTINGS file, bladiedah.

  ```yaml
  snippetPrefix: snippets/
  pageTemplatePrefix: templates/pages/
  ghost:
       url: https://zef.ghost.io
  ```

Possible future commands/plugs can implement a nice UI on top of this SETTINGS file, so you don’t have to edit YAML by hand.

Design a better logo

I'm terrible at graphic design, but here's idea for a better logo leveraging the name of the product:

  • Use the color silver (light gray)

  • Put in a markdown bullet, that is: *

Be inspired!

Make Silver Bullet run on Windows

Right now, SB doesn’t really run on windows (at least the server doesn’t). When you run the npx command, it downloads and installs fine, but then it fails. After finding the folder where npx downloaded everything, in my case under C:\Users\Zef\AppData\Local\npm-cache\_npx\3678a4af46f0276d\node_modules\@silverbulletmd\server I can run node dist\server\server.js from there with a path to a folder, and that kinda runs. But it seems plugs don’t load properly etc.

Honestly, I don’t know anything about node and Windows. Probably somebody who does could figure out what’s going wrong here. Help wanted!

Markdown table reformat

For queries, there’s attempt to make markdown tables look “pretty”. It would be cool to have this functionality as a command basically reformatting the markdown table you’re in with the appropriate amount of spacing to make it look good.

So e.g. turn this:

|Name|Age|
+——-+——+
|Pete|38|

Into

|Name|Age|
+----+---+
|Pete|38 |

Or similar

Fail to unfurl removes url

When calling the function to actually do the unfurling, this can fail and it ends up removing the original content.

Expected:
Original content is there and a message informs the user about the problem.

In my particular case, I made a typo on the yaml to listen to the unfurl event.

Documentation: #query

The query mechanism isn't documented at all and should be:

  • What is it
  • What's the syntax (we got a proper grammar definition for it
  • When does it kick in (how do you refresh the data)
  • How do you use templates to render the body (spoiler alert: handlebars with some helpers)
  • What sources are available
  • How do you implement your own data source

Link enricher/unfurl command

Since note taking often involves quickly pasting a link into a note, it would be cool (and fairly straight forward) to have a command that “enriches” a link. This could happen in various ways. In its simplest for a “naked URL” (simply pasting a URL into a page) and running the command, could fetch the URL, extract its title (e.g. from the <title> tag) and replace it with[title](url).

Another command (or the same one) could do something more link specific, for instance when linking to a tweet it could perhaps extract the text of the tweet and insert it as a blockquote.

Implementation note: while commands are run in the browser (“client”) context, performing a fetch is limited by the usual CORS restrictions, therefore an implementation likely will consist of at least two functions: one that implements the command, and uses the invokeFunction(“server”, “functionName”, …) syscall to invoke the actual logic on the server (where a fetch can fetch any URL and simply resturn the result back to the client, where the replacement can happen).

Perhaps we can also leverage the oEmbed “standard” somehow to do something intelligent.

Implement a link graph view

For many this is the "killer feature" of a that allows bi-directional linking: the ability to show all your pages and their links in a graph. See Obsidian for examples of this.

I'm sure there are off-the-shelf JS libraries that make this fairly straight forward.

Pinned pages?

This may be nice: the ability to pin pages to always be on top of the page switcher.

Dark mode

A dark theme would be a great addition to the default (light) theme. Many ways to support it (my go-to resource) but in general use the prefers-color-scheme set at the OS/browser level or do more custom persistence via localStorage, cookies, or maybe the SQLite store.

Renaming page command deletes page if default prompt input is not changed

While trying to rename a page, if the user hits "OK" in the prompt and submits the same value (since the prompt has as its default the current page name), the page is deleted.

Suggested change: check for old vs new value and make the rename a no-op in case they are equal (same behavior as when newName is falsy).

I've prepared a small PR for this #50

Docker distribution

Some people may prefer to run SB in a docker container, this may also make it easier to run it on services like fly.io

What we'd need is a Dockerfile built on top of a minimalist node8 image, preinstalling a recent version of SB via npx, but still running it via npx on boot auto-updating to the latest version if available.

The container should use a configurable volume to store the pages, and should probably make the port and password configurable.

"How to" content: PARA

It may be good to document, but potentially even create a plug with convenience commands specifically to implement the popular PARA method using SB.

Outlining commands

Currently when you hit Tab inside of a bullet list item, it will indent it, Shift-Tab will outdent it. This is standard CodeMirror Markdown functionality. It would be cool to also add “move item down” and “move item up” commands, e.g. bound to Alt-Up and Alt-Down. This should move entire sub-trees with it.

Example of “move item down”:

* This is item 1 (CURSOR HERE)
    * This is a sub-item
* This is item 2

Turns into:

* This is item 2
* This is item 1 (CURSOR HERE)
    * This is a sub-item

As “better versions” of Tab, Alt-right and Alt-down could do indent and outdent with subtrees as well.

When used inside numbered lists, items should be renumbered as items are moved around.

Offline mode deletes content

open same page on desktop and mobile

on mobile

  • turn on airplane mode
  • write "this is mobile"

on desktop

  • write "this is desktop

on mobile

  • turn off airplan mode

Expected: somehow both lines, on obsidian I see that it creates a separate page with a number 2 (mentioning for reference), a conflict like git would also work.

Observed: mobile wins and desktop line is lost.

Documentation: data objects

Fully undocumented, but implemented exist:

```data
name: John
age: 50
---
name: Jane
age: 53
```

Indexed and queryable across the entire space, e.g.:

<!-- #query data where age > 50 -->

<!-- /query -->

Updating materialized query doesn't trigger indexing

Steps:

  • have a page with a query
  • open the markdown preview cmd+p
  • on the page, update the query so the result should change
  • update query results option+q

Expected:

  • after reindexing the preview updates

Observed:

  • preview shows the same result

Add proper authentication

Currently Silver Bullet either runs unauthenticated (anybody access to your machine has full access) or in a super basic "password" mode when adding the --password mypassword flag.

This isn't great, we probably want to have proper authentication. As suggested by @Willyfrog here, it could make sense to use a library like PassportJS to add a proper authentication mechanism.

One thing to consider is: do we have a multi-user use case and do we want to support that (if so, quickly we'd also get into the whole authorization, permission and real-time collab topic)? And if not, how complicated an authentication system do we want for effectively just one account? Perhaps a simple username/password combo with temporary session tokens is sufficient?

Soulver-like calculation support

This one's a bit out there and I'm not 100% how this should work, but I really like the free form way you can write calculations in Soulver and I wonder if we can accomplish something similar in SB.

Open ideas on even how this could work purely from the UX perspective, implementation can come later.

Implement `syscall` hook in PlugOS

In #15 it was asked if it's possible for plugs to define syscalls. Right now this is not really possible (only if you implement them via a type of RPC via the event bus), but actually this would be quite straight forward to do.

Quick example of how this could be encoded in plug YAML:

name: myplug
functions:
   addNumbers:
     path: ./mysyscall.ts:addNumbers
     syscall:
         name: addNumbers # do we really need this, or could we just do "syscall: true" and use the function's name as syscall name?

And then inmysyscall.ts:

export async function addNumbers(n1: number, n2: number): Promise<number> {
   return n1 + n2;
}

And to invoke from another plug:

import { syscall } from "@plugos/plugos-syscall/syscall";

await syscall("myplug.addNumbers", 1, 2); // -> 3

In case the syscall is not implemented (e.g. because you don't have the myplug installed), this would result in the usual "Syscall not implemented" type of error you always get if you call a non-existing syscall.

Serendipity plug: random notes

Sometimes we just need randomness. Commands that may be useful:

  • Random page
  • Random page with tag (either using existing tags in the current page, or by asking for a tag)
  • Random page based on search

Improve Query documentation with operators and templates

Add two more sections:

  • One on the operators to be used in where clauses, from the top of my head we support = (equals), != (does not equal), < (less than), <= (less or greater than), > (greater than), >= (greater than or equals), and =~ (to match against a regular expression) and !=~ (does not match this regular expression). Further you can combine multiple of these with and. Example prop =~ /something/ and prop != “something”.
  • The template used with a render clause, which is instantiated for every matching query result and uses Handlebars syntax.
    • how to create a template
    • what is the syntax (provide a brief explanation and give a link to Handlebars)
    • how to use the template (already covered by the example 5.4)

Keep secrets in a `SECRETS` page

Very similar idea as SETTINGS except just for “secrets”, that is tokens for various services. This probably should be a separate file to be easily be able to exclude it e.g. when committing your space to git (by putting it in .gitignore) or when syncing it to Dropbox etc.

Question: does it make sense to attempt to encrypt or somehow obscure these tokens?

Use cases: various plugs require credentials, such as the “github” plug (using a personal token), the ghost plug (to login to your ghost blog) etc. Until now these are kept in ad hoc pages (e.g. “github-config”) but it is probably good to centralize them.

Text folding of the section under heading

I've noticed that there is missing one feature that I got used to while I was using different notes taking apps, which is text folding of a paragraph under the heading group.

It could be useful while you are presenting something and you don't want to share details of all the topics and keep the audience focused on the expanded part.

For example:

  • after folding it

image

  • before folding the paragraph under the heading

image

It could also support nesting ➰ 😸

Query provider for RSS/Atom feeds

Implement a plug that pulls in an RSS feed as a query provider allowing users to filter and render it as desired.

For instance:

<!-- #query rss where url = "https://bla.com/feed" order by lastModified desc render "templates/rss-item" -->

Image embedding

As a first step toward attachment support, it would be good to investigate using CodeMirriror’s decorations to show images inline into the code editor using the standard ![alt text](https://link.to/image.jpg) syntax.

As a principle in SB I’d really like to avoid having people to turn on preview to see the full content of a page, so inline embedding of images would be great. But we have to see if will work reasonably.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.