This place is where we track our engineering tasks and notes. We are dogfooding 🌭🐕 at the moment and working towards a point where this tool is friendly enough for others to use. Cleaning up the UI and providing some basic edit capability are some steps towards that goal.


comments

TL;DR: Effectively this page is just a scrappy plaintext reader (of Org file to be precise, for the non-Org-mode readers on our team). You should be able to edit notes and tasks in a Confluence/Notion-like manner soon while simultaneously allowing teammembers on your team to interface with this knowledge-base and project-management setup through git and thus keep a full history of your project-management and knowledge-base on their machine.

I, for example, use this file inside of Emacs but am well aware that it would be torture to ask my fellow devs, let alone non-engineering colleagues, to fire up Emacs to get any work done. 😅

Using git underneat will allow us to facilitate nifty diffing features, time-machine like features or proper roll-backs when shit hits the fan. Git is a helluva tool and its time to expose more folks to the magic (magit users will appreciate the pun here) of git without exposing them to git mechanics.

Scroll down to section Background for more information and use the top-right perspective-switch to switch between Prose and Kanban view on this document.


comments

🙊 It's very scrappy but it's a little easier than sending ox-publish HTML or LateX exports over the wire (Slack or mail) or by asking folks to learn Emacs 🙊😅.

🎯 Goal

Offer something that is way more fun/pleasant to use than Confluence and which is more tolerable than Notion. We want to bring the joy back in collaboration and are approaching this from a developer-first angle.

😭 Problem

Knowledge bases and project management tools are currently a source of frustration 😡 and devs are largely keeping notes in separate silos: in different note-taking tools or just on folders on their local machines for easy access simply because the current tools are clunky.

There is a much intel lost which hurts organizations! 📉

Removing the barriers to share knowledge helps teams keep relevant intel together 🧠 and should minimize knowledge loss when people are out-of-office or move on to other challenges. People should ideally ideate in their knowledge management/project-management tools and not be forced to document ideas there as a rote task after conception. We're out to break the barriers to make documenting and ideating together much easier -- challenge accepted. 😅

🌟 Vision

Builds

Landing

Parameterize PrimaryFeatures component

@stefano

See what I did with FullScreenshotHero. We need to do the same with PrimaryFeatures where instead of two components, one dark and one light, we just have a single component that checks the isDark prop to determine light/dark coloring and exposes all content (images and text) through props -- same as I did with the hero component.

See LargeScreenshotFeaturesDark which I just copied from TailwindUI. Compare this to LargeScreenshotFeatures to stub in the {isDark ? :} as needed.

Checkout untheme branch and start your work from there.

[61%] Prototype 01

This is the scrappy app (scr-app 🤣) that we are using to validate some early ideas.

⚒️ Mason's code: Mark tasks as =DONE= only when they are merged into branch =hack=.

[82%] UI/UX

TODO

Fix deep headings not rendering

@vidbina@stefano

See Remove Grommet-related styling is not rendered in staging.

IN SCOPING

Implement expand all functionality

@vidbina
CANCELLED

Fix baseline alignement in headings

@stefano@edris
- State "CANCELLED"  from "IN_TEST"    [2023-02-13 Mon 17:40] \\
  Sorted with https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/223 which may not be too relevant considering all the changes upcoming with the new design but for now we consider this sorted.

Run the storybook, using npm run storybook and observe headings stories or section story.

The baselines between the workflow states, the heading title and the tags is not correctly aligned and needs to be resolved.

- State "CANCELLED"  from "TODO"       [2023-02-13 Mon 17:37] \\
  Resolved by undoing the infinite scroll (Tijan sorted this)

Because of the temporary lazy-loading (infinite scroll) implementation, links to sections that are not rendered on first paint are not automatically scrolled to. This makes it practically impossible to share URLs to sections later in a doc.

We have to figure out the data eng issues to populate a full index for every page (no matter how long) such that we know how to resolve navigation to sections that are not covered within "first paint".

Note that this concern is related to Implement internal link following and Linking aids.

DONE

When expanding or collapsing a section, briefly highlight the section to indicate the scope of that section

@edris
- State "DONE"       from "IN_TEST"    [2023-02-13 Mon 17:37] \\
  Already merged into mainline

As a user, expanding or collapsing a section is sometimes confusing because it isn't immediately clear what the borders/scope of such a section is. Since thet typography does not have sufficiently distinguishing features at all times to help a user determine scope, we should use highlighting (like a single pulse animation/transition), to indicate what the object of interest (or rather, scope of interest) is.

Put this feature behind a highlight-section-when feature flag (see featureEnabled function in core/helpers).


comments

For now featureEnabled is just a dummy that always returns true but the components will already be developed to deal with upcoming customization capability.

DONE

When clicking on a section title, highlight and expand/unfold that section

@edris
- State "DONE"       from "IN_TEST"    [2023-02-13 Mon 17:37] \\
  Already merged into mainline

As a user, I expect a folded/collapsed section to be unfolded/expanded upon clicking on it.

Put this feature behind a autounfold-focused-section feature flag (see how featureEnabled function in core/helpers is used in the TOC).

DONE

Fix disc positioning issue in lists with multi-line items in Firefox

@edris
- State "DONE"       from "IN_DEV"     [2023-01-05 Thu 21:11] \\
  Closed with 65e0bdbeb8b27ad075820b585175143553e3492e

Lists seem to show their discs somewhere that is more center/middle-aligned instead of along the top. This issue can be reproduced when looking at nested lists in Firefox.

DONE

Center Prose when it is the only ContentContainer

@vidbina
- State "DONE"       from "IN_TEST"    [2023-01-05 Thu 21:12] \\
  Completed as live for a while now since da55ef834821dd8953d0597456a727a429a1bb53
- State "IN_TEST"    from "TODO"       [2023-01-02 Mon 12:54] \\
  Merged with 774baa5977cff99f1051b64427c7c2382149dbae
DONE
Enable Prose scroll on full container
- State "DONE"       from "TODO"       [2023-01-02 Mon 12:55] \\
  Wrapped up with 774baa5977cff99f1051b64427c7c2382149dbae as the overarching point

Not sure what I meant here but we have the overflow set up on the wrapper around Prose to decouple the scrollbar from the confines of the Prose component which is width-constrained. This way the scrollbar shows up along the edges of the container of Prose which looks considerably better.

DONE

Keep opacity of ToC sidebar 100%

- State "DONE"       from "TODO"       [2022-12-31 Sat 18:38] \\
  Merged to =hack= and also stubbed some activity highlighting feature.

Jessy said that he understands I'm trying to keep things clean/minimal/low-distraction but this is a bad pattern so we'll have to rip this out.

DONE

Reduce indentation of ToC

tijan
- State "DONE"       from "IN_TEST"    [2023-01-05 Thu 21:13] \\
  Reduce stem with 5576a803aa18c63d5d3760376a50df5c20866f10

Jessy mentioned that this will really improve the readability of the ToC. The stems are a bit too long now AFAIU.

DONE

Define Implement spy on content to highlight active ToC entry

@vidbina
- State "DONE"       from "WIP"        [2022-12-31 Sat 17:37] \\
  Tijan seems to understand this so we're clear on the task
- State "WIP"        from "TODO"       [2022-12-30 Fri 12:22] \\
  Clarified in [[file:README.org::*Implement spy on content to highlight active ToC entry][Implement spy on content to highlight active ToC entry]]

As a user, I want to see where in the ToC sidebar where I'm currently located in a document. This should improve spatial awareness for end-users.

DONE

Implement spy on content to highlight active ToC entry

@tijan
- State "DONE"       from "IN_TEST"    [2023-01-03 Tue 16:22] \\
  Merged into =hack=

We may have to use the IntersectionObserver API for this as @edris, @tijan and @stefano have already been looking at for other tasks and is also showcased in the following CSS-tricks article and StackOverflow thread.

My dinosaur 🦎 brain recalls similar functionality from my Scrollspy days (from Bootstrap and also outlined in this article from 2016) but I have not clue what the best-practice is for such functionality these days.

IN SCOPING

Stub a function to retrieve all parent ids for a given heading

@vidbina
IN TEST

Implement ToC highlighting on all parents for a given section (in view)

@tijan
- State "IN_TEST"       from "TODO"       [2023-01-19 Thu 15:04] \\
  Tijan has implemented something that works. We'll have to provide some implementation that may scale better but that is an opimization point.
DONE

Stub tree-structure margins/lines for ToC

@tijan@edrisa
- State "DONE"       from "TODO"       [2022-12-31 Sat 17:36] \\
  Done. Tijan brought this home and it's live already.

In order to simplify the reading of hierachy in the ToC sidebar, we want to present the user some margins/cues/lines to indicate relationships.

Kind of like the left-most tree-structure indicated by lines in the output of the tree command, we want to provide line-like visual cues such that it is easier to understand how items relate to each other.

.
├── data
│   └── Profile-20220910T222813.json
├── gen
│   └── infra.overview.png
├── ltximg
│   └── org-ltximg_190ec1b93750927668e485b3c5d4ec0bac2a7161.png
├── README.org
├── README.org~
└── README.sync-conflict-20220912-104529-HONTRKX.org
DONE

Create about section

@tijan@edris
- State "DONE"       from "IN_TEST"    [2022-12-31 Sat 17:36] \\
  Done but content needs to be updated. Different problem tho.

Stub a place where we can provide legal notices and other app information that may be useful to users of the application.

Things we'll need to list there:

CANCELLED

Increase padding between section collapse/expand chevron and text

@tijan@edris
- State "CANCELLED"  from "WIP"        [2023-01-03 Tue 16:27] \\
  Awaiting design input from Jessy before we continue

For the sake of consistency we want the gap between the expand/collapse chevron and the left-most line of the headline text to be a bit wider.

Furthermore, we also want the anchor link icon to show up before the text such that the link icons always show up along the same place (on the x-axis) as opposed to the current situation where these anchors show up at the end of the line (which could be anything since line-lengths vary quite a bit 🤷🏿‍♂️).

My expectation is that working on the left-most spacing of the chevron may require us to address the padding/margin on document components such that the alignment is correct. Conceptually it would be fair to introduce a invisible left-margin along which we left-adjust text as sketched https://app.excalidraw.com/l/AoDvHfNWirc/2ogauhhMKj5.

Things to be done:

Possible designs are (in order of preference):

DONE

Restyle comment views

@tijan
- State "DONE"       from "IN_DEV"     [2023-01-06 Fri 14:33] \\
  Right-aligned comments for now.

Since comments are interspersed through a text rendering them in a right-most column may be tricky.


comments

Rendering comments in a separate columns, may require us to

Observe the COMMENTS DISPLAY section in https://app.excalidraw.com/l/AoDvHfNWirc/2ogauhhMKj5 for input as to how to structure comment blocks in a desktop view.

DONE

[100%] Add fonts

@tijan
:COOKIE_DATA: todo recursive
- State "DONE"       from "WIP"        [2023-01-06 Fri 14:35] \\
  Fonts needed for now are added.

Not sure if the following links are relevant here:

DONE
Add emoji font
@stefano
- State "DONE"       from "IN_SCOPING" [2022-12-23 Fri 21:34] \\
  Done with Tijan!

Emojis are currently not consistently rendered. On my Linux box, I see a painful mess of just monochrome Wingdings-style emojis and the more colorful icons. Setting up an emoji font to ensure that everyone sees the same thing would improve consistency here and should be a small enough win for us to lock in.

From a chat with @stefano it appears that this may be tricky to accomplish without some heavy content moderation magic. So we're going back to Twemoji https://github.com/twitter/twemoji.

A way to implement this may be to use https://www.npmjs.com/package/react-twemoji and wrapping text-bearing components inside of a Twemoji component in order to bring in that conversion magic. Manually modifying the text at this point through custom-code would be premature optimization for what we need atm. We just need something to fix the consistency problem: emojis looking very different between Windows, MacOS/iOS, Linux and Android because the browser default to the platform-specific emoji assets.

Just spoke with Edris and perhaps we something like pulling in a Noto Color Emoji font https://fonts.google.com/noto/specimen/Noto+Color+Emoji would be a more scalable fix. Anything that rewrites the DOM is pretty heavy and will cost us down the line but just plain ol' fonts may be a must gentler solution to this problem.

DONE
Add attribution for Twemoji
@tijanlegal
- State "DONE"       from "TODO"       [2023-01-06 Fri 14:35] \\
  Added with 674be5927832d0d066d1ff480112d74eb47e5e69

Tijan is already stubbing some place/option modal/tooltip/sidebar or whatever seems most practical where we can drop legal notices and other background information of this sort.

DONE
[100%] Add text fonts
- State "DONE"       from "TODO"       [2022-09-28 Wed 13:57] \\
  Completed with https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/93

On different platforms the selected serif font will look different. In order to control the quality of the reading experience, let's pick a decent open font to use here.

It is important the the fonts have varying weights such that we can still distinguish from bold text when it is presented inside of a Headline which is already presented in bold.

DONE
Add serif font
DONE
Add sans-serif font
- State "DONE"       from "TODO"       [2022-09-28 Wed 13:56] \\
  Merged with https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/93

Here are the options approved by @siarhei:

TODO

Collect all tags for a document and color-code them

@vidbina

For readability's sake, we want to color code all the tags such that the same value tags always appear in the same color. This should allow readers to visually associate related items provided that the readers/observers are capable of discerning the colors.

As a follow-up point, we should define a task to break inventorize which colors are fair to use from an a11y perspective in order to maximize the serviced audience by this feature.

CANCELLED

[0%] Restyle reader entrypoint

@vidbina
- State "CANCELLED"  from "WIP"        [2023-01-06 Fri 14:36] \\
  Cancelling since we're probably changing the general approach. Current entrypoint remains until new design direction/requirements are clarified.
- Note taken on [2022-09-05 Mon 22:32] \\
  Instead of creating a UI flow, we are improving and simply rendering the Engineering document at index. This is a quick-fix to buy us some time. 😅

Page /reader/index needs to be restyled to align stylistically with the main reader, otherwise users may be confused into thinking that these are different apps.

What basically has to happen:

DONE

Display ToC in hamburger menu on mobile

@tijan
- State "DONE"       from "TODO"       [2022-12-23 Fri 21:36] \\
  First prototype delivered by Tijan

When accessing from a mobile device, the table of contents is no longer visible. We need to fix this to provide some ability for a reader to navigate through a text.

The top of the hamburger menu contains an avatar and some placeholders for controls that we may need in the future, we can add a container underneath that displays the ToC.

DONE

Standardize ContentContainer buttons

@edris
- State "DONE"       from "TODO"       [2022-11-25 Fri 10:51] \\
  Merged with 08e7c4302406c4753d182a5e6b95e33681820b6d

Within ContentContainer, we need all buttons to show up in a uniform style. Perhaps we accomplish this by defining a ContainerContainer-internal component that has the background and the rounded borders that we can reuse.

Furthermore, I want all buttons to be rendered with about 50% opacity and become full-opacity when hovered over. Just to make them a bit less "in your face".

DONE

Restyle ToC to be less in your face

@stefano
- State "DONE"       from "TODO"       [2022-12-06 Tue 07:22] \\
  merged with 38065af94065626fe1584f67a47a13c30497d241

The current ToC is quite prominently (almost aggresively) present with the high contract white-on-dark design. Let's

CANCELLED

Setup themes

@tijan
- State "CANCELLED"  from "TODO"       [2022-11-17 Thu 11:49] \\
  Not in need of themes for now. We'll just service a base case and count on folks using extensions such as DarkReader to have control over dark-mode.
DONE

Fix ToC Disclosure animation

@tijan
- State "DONE"       from "TODO"       [2022-09-07 Wed 22:09] \\
  All handled by @tijan 🏆🥳

When expanding/collapsing the ToC sections, the disclosures are not smoothly animated. The setup seems to be unaware of the changing height of the children and only effects a height-related change when the child elements are removed altogether which creates a bit of a visual shock as the space for the children instantly disappears from one moment to another.

I very likely lack the lingual skills to explains this very clearly, so just have a look in the storybook and then hop into my Google Meet room for us to talk it through for clarification.


comments

💡 I'm an idiot! Whatever animation I currently implemented there is horrible. Especially on the longer list displayed in the index, the ugliness is very pronounced. It all looked decent in the shorter lists in Storybook but now it's clear that we can remove whatever I did there.

It's so ugly it's technically criminal! My "engineering" license should be revoked for this one. 😅 Good thing I don't do this for a living.

CANCELLED

Design DocumentPart

- State "CANCELLED"  from "TODO"       [2023-01-11 Wed 16:38] \\
  Not sure what this means now.

Note that every section can contain its own definition of title

DONE

Implements Date components

@tijan@assutech
- State "DONE"       from "TODO"       [2022-09-04 Sun 16:21] \\
  Just merged to mainline and added some notes in-source tagged to @tijan about restructuring the architecture to optimize DRY-ness of the setup.
DONE

Style fallback components

@tijan@assutech
- State "DONE"       from "TODO"       [2022-08-29 Mon 13:18] \\
  Merged with https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/50
TODO
Build storyboards
- State "DONE"       from "TODO"       [2022-09-14 Wed 11:40] \\
  Already live!

Based on HN input by moeffju, we do readers a service by not displaying non-functional anchors and nudging them into trying to use them and getting lead astray. This is totally on-point so, let's remove all anchors until we sort out the link following.

DONE

Fix TOC Storybook

@tijan
- State "DONE"       from "TODO"       [2022-09-25 Sun 21:01] \\
  Done by @tijan and already merged. Had something to do with me resolving a merge to use a element instead of divs. 🤦🏿

The TOC is broken in Storybook and this Stack Overflow thread may provide some explanation of the issue at hand. Let's either fix the Storybook or figure out of this case is not testable in Storybook and then just make a note of this issues such that future developers know not to attempt testing click-through inside of Storybook.

DONE

[66%] Design headline linking strategy

@vidbina
- State "DONE"       from "TODO"       [2022-09-25 Sun 21:03] \\
  Mark headline linking as done for now.
Background
Requirements

Headlines ids can not be randomly generated on a per-session basis (to map between ToC entries and headlines) as these id are not guaranteed to be the same during another session and therefore not shareable.

Bookmarked links need to survive non-destructive diffs (when just new content is added).

If the headline is removed then notify the user that the link has been removed at a given version, timepoint $t$, and provide an option to navigate to state $t$ to view the headline anyways

Approach

Rough outline how we will deal with headline identifiers.

This is the scenario where a headline is completely created within our tool.

⚠️ Any headline created in another tool is not guaranteed to satisfy the characteristics of a headline populated by us so, we have to be graceful in how we handle headlines. 😅

This operation does not mutate the document in any form.

With indexing we keep track of headline identifiers throughout the lifetime of a document. This indexing should enable us to provide guidance to the user when a link is followed to a headline that may no longer be there or may have been modified (for example when a CUSTOMID is defined for a heading that was previously referenced through the id obtained by the heading-to-id conversion logic).

TODO
Heading-to-id conversion logic
:ID:       904ea339-a66d-4c68-8278-7b80594f9e70

Org implements its own <<<heading-to-id conversion logic>>> that roughly works as follows:

- State "DONE"       from "TODO"       [2022-09-25 Sun 21:02] \\
  Mark link following on headline links as done.

Following links is a core feature of any document. Let's provide some basic implementation. In the long-tail, we will need to keep track of heading references over the lifetime of a document just to ensure that we can provide useful guidance on how to resolve links (for example, inform a user to go back to a previous version of a document).

- State "DONE"       from "TODO"       [2022-09-23 Fri 17:37] \\
  Index can be populated but we are populating it at the end of parsing instead of populating it on an ongoing basis. The reason for this is that I simply couldn't figure it out fast enough. Recursing over a document leaves the problem of sharing some document-global state to verify that human-friendly slugs do not collide. Trying to do this with map/reduce like mechanisms is problematic because the index state is copied along and there is a change that competing branches settle on the same slugs, allowing for collisions.
  
  Sleep deprivation and tunnel-vision are almost certainly in the mix here, so after a chat with @stefano we opted for the dead-simple approach of generating unique ids for now and then indexing them post-parse. This sucks because we now have to figure out how to lookup the human-friendly slugs in the rendering step. This will require us to pass some document-local state along to all the render functions. Just ideas. Maybe this is all BS and we'll find a better design after we've enjoyed quality sleep. 🤷🏿‍♂️

Links such as [[*Headline]] should basically work and resolve to the first match. So if there are multiple headlines with the same text, the first one is always the one reached by such a link.

We can link to a headline by providing the headline text sans the keyword, statistics cookie and tags. Observe list item 1 in the snippet below that demonstrates a valid link to the headline defined at the bottom of the snippet.

The following links will link to the section below:
1. [[*\[#B\] This is a *bold* heading][link]] works
2. [[*This is a *bold* heading][link]] does not work because the prio is missing

Now follows the section that we link into:

* TODO [%] [#B] This is a *bold* heading :taga:tagb:

Here we are

***** This isn't love, this is destiny

One of the previously working links was a trick. It was formatted incorrectly. The link below is simply because it is of a basic headline without any fancy bells or whistles.
[[*This isn't love, this is destiny][a link with interesting punctuation]]

***** TODO [#A] COMMENT [100%] This isn't love, this is destiny :a:b:c:

The following link is trickier because it basically contains all the bells and whistles that headings can afford.
[[*This isn't love, this is destiny][correctly formatted link to self]]

***** TODO [%] [#B] How are you

Below is a link to a trick heading. The order of the heading metadata is really important so here we have a link containing the priority metadata because we listed it in the wrong order in relation to the statistics cookie.
[[*\[#B\] How are you][wonky link to self because priority is listed before statistics cookie]]

***** TODO [%] [#A] This isn't love, this is destiny :lyric:

Here is an example from the tests in the code. The uniorg parser seems to return all of the metadata along with the heading text =[%] [#A] This isn't love, this is destiny= but Org (in Emacs) only returns the escaped priority along with the heading text
[[*\[#A\] This isn't love, this is destiny][link]]

* TODO [#A] This isn't love, this is destiny :lyric:

***** TODO Populate shareable heading [%] ids

[[*Populate shareable heading ids][link]]
DONE
Populate shareable heading ids
- State "DONE"       from "WIP"        [2022-09-25 Sun 20:37] \\
  Done with latest merge to hack (see https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/88)
- State "WIP"        from "TODO"       [2022-09-23 Fri 17:43] \\
  We are currently generating these ids through a helper function which runs through the flat list of headings and produces all slugs that we need. In an ideal world, I imagine populating an index while the document is being transformed (to our internal representation). Fundamentally, I'm torn on whether this information belongs in the internal representation of the headings. Part of me says that slugs, ids and linkTexts belong in the heading while another part says that we should just keep these in indices and provide a fast reference to the data (the heading).

Multiple headings which resolve to the same plaintext, should be numbered such that the id uniqueness constraints remains honored (a given id may only exist once).

We cannot use PRNG-generated heading ids because such ids will be different between sessions.

* C

Should be referred to by id =c=
* C+

Should be referred to by id =c-1=

* C++

Should be referred to by id =c-2=

Kind of how GitHub ids README headings.
DONE
Generate unique id for every parsed headline
@vidbina
- State "DONE"       from "TODO"       [2022-09-23 Fri 17:46] \\
  Consider the scrappy part done!

The availability of unique ids for every parsed headline may simplify the implementation of linking. Within a session we can just use the session-scoped unique ids.

These ids will not be stored as data as they are only meant to be used within the intermediate representation to provide us quick references that are "guaranteed" to not collide within a session scope.

With such unique ids, we simplify the implementation of linking as we can just implement a lookup table that points headline links, CUSTOM_ID links, ID links or other linking methods to a single reference.

We'll stub a scrappy implementation and will optimize later. 😅

TODO
Look into uniorg-slug and figure out if we should use this instead to honor CUSTOM_ID right away
@vidbina

The current implementation is extremely scrappy but reading through the uniorg codebase is seems that uniorg-slug already covers part of this functionality in a much cleaner way.

[66%] Linking aids

Linking is a little bit easier now, but we are still lacking some visual aids/cues that can make is considerably easier for readers.

- State "DONE"       from "TODO"       [2022-09-27 Tue 13:00] \\
  @tijan came to the rescue 🏆 with https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/91

As a user, I want to be able to obtain the link to a heading by simply clicking it or by clicking some paragraph-icon (like ¶) or link icon alongside it (let's start with towards the end of the heading text).

Clicking a headline link shoulf link to itself and update the URL to that specific heading.


comments

Clicking the link icon (whether it is ¶ or something else like the link icon to the left of headings on GitHub README pages) should link to the heading by id.

Currently, I can only obtain this link by through the TOC. This is not very convenient when I am already scrolled to a certain part of the text and want to obtain some context by simply refering back to the ToC.

Link for a heading can be obtained by passing looking up the heading id in the headingIdToSlugIndex index on the document (type FDocument). See the TOC, where the lookup is being performed.

DONE
Highlight highlighted ToC entry and Prose entry when navigated to from URL id
@tijan
- State "DONE"       from "TODO"       [2022-09-28 Wed 21:45] \\
  Merging with 4d5dcbc3542b254fcff861ff5f14e1631202b13c

When we navigate to a given heading through clicking an entry in the TOC or by following a link such as DOMAIN.TLD/PAGE/#heading-id, where heading-id is the heading id, we want the active id to be highlighted in the view such that it is easier for the user to spot it.

TODO
Highlight all parent ToC entries
@tijan

Sometimes entries highlighted in the previous task are hidden because the parent may be collapsed. As a user, I want all parents highlighted until the topmost that isn't folded away. This should allow us to follow the trace when we are unfolding the ToC tree to find our intended entry.

💡 It would be an idea to automatically unfold the tree to show the highlighted entry but this may be too disruptive if the user has folded the tree into a particular view for better overview. The idea of tracing the parents by higlighting them would be less disruptive to a reader's workflow.

Upon sorting out a headline linking strategy, we can implement functioning anchors or buttons wherever we have links. The links listed in the document and in the TOC would need to be updated to facilitate linking.

- State "DONE"       from "IN_TEST"    [2022-12-29 Thu 12:20] \\
  Thanks to Tijan 👑
- State "IN_TEST"    from "TODO"       [2022-12-29 Thu 11:20] \\
  Fixed with 90fde61f19338ca44b6c626b93854e36892304e2 in vidbina/fix-dropped-path-for-links-in-non-std-spaces

When visiting links on non-standard (not our dev board) spaces, the path is dropped from the heading-level links/anchors. So instead of going to DOMAIN.TLD/PATH#ID the anchors navigate to DOMAIN.TLD/#ID which is killing the usability on non-default pages.

DONE
Implement temporary highlight of selected section upon follow
- State "DONE"       from "TODO"       [2023-01-06 Fri 14:22] \\
  Merged into mainline with a post-it style highlight on the section and ToC entry. We still need to "unwap" nested sections when they are folded to make some sections visible.

When following links, it isn't always clear where the reader is to focus their attention. Highlighting the ToC section along with the Prose section in a brief flash or something of that sort may solve this UX issue.

Observe Highlight all parent ToC entries which should be the step before we can unwrap sections on an as-needed basis.

- State "DONE"       from "TODO"       [2022-09-23 Fri 17:47] \\
  The TOC now links through to the unique ids that we generate with the help of =nanoid= at the moment.

As an example for the later implementations.

:COOKIE_DATA: checkbox recursive

Internal document links in Org can refer to a headline by

Implement the indexing logic to facilitate heading lookup by the tokens mentioned above.

:COOKIE_DATA: checkbox recursive

The headline links in Org texts are actually called fuzzy links and they fuzzy link values are derivatives of actual heading text.

The following points are copied from the subpoints below:

Where in the Org-mode codebase is this implemented? Link to the source for future's reference.

Observe that headline fuzzy links are formatted as follows: Verify how [this] heading with an asterisk* links*, where:

Which means that we need to keep these changes in mind when indexing fuzzy links for headings.

Observe that headline fuzzy links are formatted as follows: Verify how heading with cookie links 🍪

Link following in Prose view requires an index to be populated which is a blocking task.

TODO

Implement breadcrumbs

Upon navigating to a headline, we want a breadcrumb to indicate the level at which the document is being observed. This breadcrumb view can be used as a method of narrowing the Kanban view as well.

[0%] Images

Images in the document need to be rendered correctly. We have no images in this document yet to demonstrate this but this task is here to expand on this point.

[0%] Filters

IN SCOPING

Stub filter component

As a user, I want to be able to filter what I can see by tag, date, workflow state, section title or section body content. This is effectively a search function.

TODO

Implement filtering logic

[9/9] Auth

Evaluated auth libraries or services like Auth0, NextAuth, Clerk.dev and ory.sh with the end-goal of optimizing for best ease of use and minimal ops/management load.

As per , we're doubling down on ory.sh after trying NextAuth and realizing that it limits us to doing everything in NextJS. Furthermore, NextAuth allows for little control over the user journey which may trigger a need for reimplement soon in order provide a clearer UX and such a reimplementation would almost certaintly require us migrate NextAuth data.

DONE

Fix positioning for auth control @edris:

- State "DONE"       from "TODO"       [2023-01-06 Fri 14:41] \\
  Fixed with 0d3acdf1fc4e1244207f56536205666bf23055ea

I've added some UI for Auth (see AuthControl.tsx) that proposes a Popover that is not correctly positioned


comments

it appears under the button that invokes it and is aways center-aligned in relation to this button which becomes an issue when the button is right-aligned. The popover now gets partially rendered off-screen.

This doesn't have to be a popover and could also be a sidebar like you used in the About modal.

Your idea on implementing this is likely considerably better that whathever the monstrosity is that I cooked up in my effort to move fast. 😅

CANCELLED

Prepare database

@vidbina
- State "CANCELLED"  from "IN_SCOPING" [2022-12-09 Fri 02:30] \\
  We're focusing on ory.sh for now, which provides a batteries-included kind of path.

Updated the general scope of the Auth concern such that we don't have a large persistence burden on our-end since we are using a managed service for auth.

DONE

Facilitate login-with-GitLab

- State "DONE"       from "IN_DEV"     [2023-01-06 Fri 14:43] \\
  Handled with Supabase Auth for now and already enabled
DONE

Facilitate login-with-GitHub

- State "DONE"       from "IN_DEV"     [2023-01-06 Fri 14:43] \\
  Handled with Supabase auth and already enabled
CANCELLED

Facilitate login-with-Google

- State "CANCELLED"  from "IN_DEV"     [2023-01-06 Fri 14:43] \\
  To be handled with Supabase Auth, will be a matter of configuration. Implementation is there but configuration is cancelled until we need it.

We first need to made a decision on how we deal with non-git data.

CANCELLED

Setup NextAuth for GitLab

@vidbina
- State "CANCELLED"  from "TODO"       [2022-12-09 Fri 02:30] \\
  Using ory.sh for the reasons mentioned previously
CANCELLED

Setup NextAuth for GitHub

@vidbina
- State "CANCELLED"  from "TODO"       [2022-12-09 Fri 02:31] \\
  Using ory.sh for the reasons mentioned previously
CANCELLED

Setup NextAuth for Google

@vidbina
- State "CANCELLED"  from "TODO"       [2022-12-09 Fri 02:31] \\
  Using ory.sh for the reasons mentioned previously
CANCELLED

Solve login to same space from different IdPs

@vidbina
- State "CANCELLED"  from "TODO"       [2023-01-06 Fri 14:44] \\
  Not needed for early stage, probably more of an enterprise thing. Just a fun idea that adds no value for now.

As a user, I want to be able to login with my GitHub account or my Google account and see the same data if I use the GitHub account for the same org as my Google account. For this to work, I need to be able to associate multiple ids from various IdPs to the same invididual.

CANCELLED

[0%] Spaces

- State "CANCELLED"  from "IN_SCOPING" [2023-01-06 Fri 14:53] \\
  Cancelling to revisit when we really start to deal with forge integrations and determine that this is a must-have.

With spaces we initially meant a "space" as a container for files in a given context like an organization, a department or perhaps even a "mindspace" or "headspace" like "things to do in BKK in 2022" or "prompt engineering".

I'm (personally) leaning towards the latter but this may break the everything-in-git model. For simplicity's sake, we should opt for the first approach and probably drop the notion of spaces altogether unless an end-user wants to see their multiple forge orgs within the same session.

IN SCOPING

[0%] Persistence

IN SCOPING

Facilitate text authoring/editing

Just grabbed coffee with Marijn Haverbeke from ProseMirror and CodeMirror to explore how to approach this problem and whether to focus on collaborative editing right away.

ProseMirror offers OT-based collaborative editing. See https://marijnhaverbeke.nl/blog/collaborative-editing.html and https://prosemirror.net/docs/guide/#collab for relevant background information.

💡 We can implement authoring/editing without auth or persistence by just allowing folks to copy/paste the source. Really bad UX but I'm just saying that we can implement the UX side of this experience without blocking it with back-end-ish concerns (auth and persistence/storage).
TODO

Implement commit-to-git

TODO
Implement commit-to-GitHub repo
TODO
Implement commit-to-GitLab repo
TODO

Implement non-git storage

TODO

Implement multiplayer session store

For collaborative editing (multiplayer mode) we will need to offer a storage overlay that facilitates ephemeral data (like collab session interactions) until these are solidified enough to convert into a change request/MR/PR by way a git commit.

Some of the options in consideration are replicache, liveblocks and Yjs (which is P2P but may still require some information overlay to coordinate session discovery).

TODO

[50%] Adapt parsing options based on document input

@vidbina
:ID:       542046cc-0783-4be1-bf6c-7a592d6e96e3

comments

⚠️ This task is oddly unspecific. The core point here is that there are settings encoded in a document body that we need to honor in our representation efforts. This means that we have to extract our parsing configurations from the document text (since some configuration is embedded therein) which almost certainly will require multiple passes in order to acurately parse/process a document. Eventually, we can cache these values to minimize the need to parse things immediately and on the fly.

The defaultOptions for the uniorg parser sets todoKeywords to TODO and DONE (see src) which is in line with Org's defaults. Custom TODO keywords that are defined through the TODO keyword or its variants TYP_TODO are not being honored and thus these keywords are parsed as "just text".

Examine how to make the parser options region dependent such that we can parse differently within limited scopes (for example parsing with certain keywords known for the scope of a section where these keywords are defined) how to implement honoring of TODO keywords that are defined to be file-local.


comments

💡 Perhaps we can study the streaming API of uniorg to figure out to which extend we can modify the options data structure and whether this mechanism implements some stack such that we can pop out of a given context in order to continue parsing of a document.

Streaming API won't help here as we need to sculpt/adapt/shape the document as we obtain more information. The streaming API may be helpful for the large file parsing timeout point.

See https://github.com/rasendubi/uniorg/issues/53 with the following response to our issue:

Definitely in the scope of the project. This is also closely related to
=#+OPTIONS= as they also influence how file is parsed.

The main challenge with these is that they can occur anywhere in the file.
Options or todos might be specified on the last line of the file and they
should still affect all the lines above. (In emacs, I believe they set
buffer-local variables and re-fontify. That's why you have to C-c C-c when
you change options line.)

The easiest way to implement this in uniorg is to parse file twice. First
time to extract keywords, and second—with options configured from the first
parse.
DONE

Parse document twice to collect TODO sequences

workaroundhack
- State "DONE"       from "TODO"       [2022-10-15 Sat 15:42] \\
  Already implemented.

Disclaimer: This is a sloppy solution but will definitely work for now. Let's just get this to work reliably even if slow and shittily implemented. 💩

I already considered just parsing $n$ lines prior to parsing the full document in order to minimize the workload and keep things "responsive" but this is not the prime objective at the moment.

Keywords that we need to check for TODO sequences are:

TODO

Inventorize which keywords are relevant for us to present documents correctly

See https://orgmode.org/worg/dev/org-syntax.html#Keywords for the definition of keyword. We need to parse

🦬 Yak Shaving/Background

Note that defaultOptions in parse-options.ts defines TODO and DONE as the default values for todoKeywords. According to a code-base grep, the only place to change the defaultOptions seems to be in the constructor of the Parser in parser.ts. The implementation in parser.ts doesn't seem to allow for updating of options during parsing.

TODO

Render all block using the Fallback component

Currently many blocks remain unrendered. This should be resolved by rendering all block-like components in a Fallback component as a interim quick-fix.

IN SCOPING

[0%] Display task progress

TODO

Update uniorg to get statistics cookies

debt@vidbina

We contributed to this feature but haven't bothered to update yet. In order to display task progress, we'll need it so let's get on with it.

TODO

Show Heading progress

As a user, I want some visual indicator of how far along something is.

Progress indicator has various modes:

WIP

Determine color-scheme to use to communicate progress

@siarheidesign

As a user, I want progress color-coded to provide a quick sense of where things are.

In Emacs, completed or terminated tasks are rendered in green while ongoing tasks are rendered in red. This is sometimes a source of confusion because some may associate red with stopped and green with go given the usage of these colors in traffic lights and other problems (see Show Heading progress) to provide a more fool-proof solution here -- something that is less prone to misunderstanding.

We want something that is instantly clear with just a split-second glance. Perhaps we need to rely on a combination of color and shapes.

TODO

Figure out what to do with this

@vidbinadebt

We probably want to gradually alter the color a WorkflowState in a workflow according to some gradient. Not clear what to do here yet. Ask design for input.

💡 See ~WorkflowStateColor~ in renderer.
TODO

Extract extreme states for a given workflow

@vidbina

Terminating states are easy because we parse them into our data structure into workflows with the isActive property set to false.

Starting states are a bit trickier, but we can start by assuming that the first non-terminating state in a workflow are the starting state.

When multiple workflows are defined, always take the first of each workflow to indicate a starting state. So we should be able to support multiple starting states this way.

CANCELLED

[37%] Multi-pane Layout

:COOKIE_DATA: todo recursive
- State "CANCELLED"  from "IN_DEV"     [2023-01-06 Fri 14:51] \\
  Unclear how critical this is. User can use multiple windows if this is such a big deal for them.

As a reader, I may sometimes want to have content juxtaposed to simplify reading or x-ref-ing. Perhaps I want two instances of Prose (scrolled to different locations) side-by-side, perhaps I want a Prose view shown next to a Calendar view.

We need the basic mechanisms in place to facilitate this for experimentation.

DONE

Implement resizable pane component

@tijan
- State "DONE"       from "TODO"       [2022-11-23 Wed 06:38] \\
  Been implemented using ResizablePane

As a user, I want to be able to resize a pane to fit my needs.

The pane should be resizable in the following modes:

When dragging we want to have clear borders visibly to guide the end-user in understanding what the frame is that is being dragged.

Our first implementation should just render an empty Pane. Don't worry about the content for now.

DONE

Migrate perspective control into the Pane

- State "DONE"       from "TODO"       [2022-11-23 Wed 06:38] \\
  Done through introduction of ContentContainer

As a user, I want to be able to view content inside of a Pane and potentially be able to study multiple instances of a given perspective side-by-side.

Currently the control of perspective is global (in the navbar) and in order to do panes well, we want to delegate this control to the Pane level such that viewers of multiple panes can control the perspective of each pane within that pane itself.


comments

If we don't provide pane-local perspective control, we will have to provide users to mechanism to control which pane they refer to when switching perspective in a global (in the top navbar) control. This will already confuse us as users, let alone another user.

CANCELLED

[0%] Implement pane-splitting

@jessy
- State "CANCELLED"  from "IN_SCOPING" [2023-01-06 Fri 14:50] \\
  Was an early brain-fart, and it is not clear if we will really need this since people can split their windows as well if this is so important to them. 🤷🏿‍♂️

Earliest brainfart: Provide split-horizonally and split-vertically buttons somewhere in the pane to allow the user to split the pane how they want to. From that part on users can use the pane-local perspective controls to manage that pane.

TODO
Stub ContentContainer
@jessy@tijan
⚠️ Focus on desktop experience.

We are going for a Pane-oriented approach in usage where users can click through a document and open successive panes of different types. Furthermore, users should be able to switch the type of a pane from, for example, from source to prose to calendar to kanban.

This task is the starting point to providing a base container that can be used to facilitate the composition of arbitrary panes. The user will be able to inform/control which panes are in view based on the manner in which they step through (or explore) a document.

See https://app.excalidraw.com/s/AoDvHfNWirc/4SswRbCtpkN for some sketches on the overal flow. These have been roughly explained to @jessy, @stefano and @tijan meanwhile in case you're looking for someone who can help clarify these points.


comments

A tool such as Glamorous Toolkit allows for a pane-oriented workflow that comes close to that which we are also thinking about.

We are not incorporating the ToC sidebar inside of the ContentContainer as @jessy clarified this to be an antipattern and we should just opt for a single global ToC sidebar which is alway highlighting the active entry in the pane currently in focus.

TODO
Clarify not building pane-oriented ToC's
@vidbina

@Jessy explained pane-scoped ToC sidebars to be an antipattern so we have to make sure that the developers working on this know to not spend energy on this bit. Furthermore, task following from Define Implement spy on content to highlight active ToC entry will tackle the implementation of the ToC sidebar highlighting capability that is refered to here.

The ContentContainer should not occupy itself with such concerns. 🧐

TODO
Implement split-pane-horizontally in pane controls
TODO
Implement split-pane-vertically in pane controls
TODO
Implement close-pane control

[20%] Source Perspective

DONE

Stub a source perspective

@tijan
- State "DONE"       from "WIP"        [2022-12-30 Fri 12:38] \\
  Tijan delivered this one and it needs to be integrated.

As a author, I want to be able to edit the Org or Markdown source of the document in a non-WYSIWYG manner for optimal control.

This is a cheatcode to not have to built in the WYSIWYG editing capability from the start.

The usage mode here is comparable to the HedgeDoc https://demo.hedgedoc.org/.

TODO

Prepare Org syntax-highlighting

@tijan

Within the source perspective, we want Org syntax to be highlighted correctly. We may have to write an extension (or whatever the name is for some extension to the code editors native capabilities) to cover this.

IN TEST

Integrate Source Perspective

@tijan

As a user, I want to be able to switch to Source Perspective as one of the perspective candidates so I can eventually examine and edit the source of the document.

We're talking prototype level so we don't worry about optimization issues such as debouncing.

TODO

Disable auto-render onChange and provide a button to refresh

@tijan

Since we can't provide a sub-100ms parse/render cycle (yet), we shouldn't run our heavy multi-sec blocking parse/render cycle on every keypress. We can do either of the following:

Just fuming ideas here and I think idea 1 is easiest so let's do that one first and then think about idea 2.

TODO

Research ways to optimize source perspective reactivity

@tijan@vidbina

Looking at HedgeDoc's editorpane (which also uses React CodeMirror), we probably should be using some extension to handle changes (instead of stubbing onChange handlers directly). This is probably not affecting performance much but rather an architecture/design concern.

I'm unclear on how changes are fed back into the rich-text output. From a cursory glance of the Chrome DevTools Performance flame chart recorded during input, it appears that we parse (input) and render (to HTML) upon keyup. This still feels very snappy in HedgeDoc and they kind of do the whole parse/render-to-HTML dance upon keyUp as well, so we'd have to figure out if they a full parse/render cycle or if this is incremental parsing at work.

From my recollection of CodeMirror-related tooling, my guess is that HedgeDoc uses incremental parsing (the Lezer parser is a staple in CodeMirror-land). This can be the reason why HedgeDoc feels snappy. Uniorg doesn't do incremental parsing which is part of the reason why any update may feel rather expensive.

💥 Just did a quick check and any of our parse calls may take north of 1 second, whereas v.parse in the HedgeDoc app take only 4.92 ms. In our case, performance is even more degraded as we parse twice.

[0%] List Perspective

TODO

Define what we mean with List Perspective

@vidbina

This look a bit like Linear but needs better definition.

[66%] Prose Perspective

DONE

[100%] Implement Section folding

- State "DONE"       from "TODO"       [2023-01-03 Tue 16:32]
DONE
Implement a Section component
@tijan
- State "DONE"       from "TODO"       [2023-01-03 Tue 16:31] \\
  Already in mainline

Implement a section component that uses something like headless's Disclosure to make the entire section foldable.

DONE
Render Section component in renderer
@tijan
- State "DONE"       from "TODO"       [2023-01-03 Tue 16:31] \\
  Completed

Currently the renderer doesn't render anything for a section (we just return an empty list). We may need to think through what rendering sections will "mean" since there are a lot of nested sections in a doc, so once we start rendering sections we should expect some fireworks. 🎆

Let's not worry about the explosions for now and just get this implemented! Once it's there it'll be my chore to figure out how to clean things up when merging the changes.

DONE
Fold completed sections Prose
@tijan
- State "DONE"       from "TODO"       [2023-01-03 Tue 16:32] \\
  Merged in mainline already

Minimize the noise in the docyment by folding all sections that are marked as DONE, same as Fold completed headings in ToC, above.

DONE

Fold completed headings in ToC

@tijan
- State "DONE"       from "TODO"       [2022-09-27 Tue 13:04] \\
  Implemented by @tijan with https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/92

Minimize the noise in the ToC by folding all the headings that are marked as DONE (todoKeyword from type FHeading).

TODO

[50%] Implement Drawer

DONE
Stub Drawer
@tijan
- State "DONE"       from "TODO"       [2023-01-05 Thu 21:49] \\
  Merged with c4d748e4df2c290b9cb338bab5fd0e6cc7f42142

Mostly following the comments idea as discussing in the chat https://app.excalidraw.com/s/AoDvHfNWirc/2ogauhhMKj5

TODO
Extract properties blocks and render in drawer
@vidbina
DONE

[100%] Implement Comments

- State "DONE"       from "TODO"       [2023-01-05 Thu 21:20] \\
  Closing comments implementation for now
DONE
Parse block comments
@vidbina
- State "DONE"       from "TODO"       [2022-09-25 Sun 20:57] \\
  Block comments are already being rendered albeit not in an optimal presentation.

I know what this means but essentially I want to be able to parse comments that are formatted as follows:

#+begin_comment
This is a comment
#+end_comment

and appears as:


comments

This is a comment

DONE
Parse inline comments
@vidbina
- State "DONE"       from "TODO"       [2022-09-25 Sun 21:10] \\
  Just verified that this works!

Readers need to be able to read inline comments such as the comment below:


comments

This is an inline comment and should be visible on the page!

DONE
Stub Comment component
@tijanassutech
- State "DONE"       from "IN_TEST"    [2022-10-15 Sat 21:48] \\
  Tested and integrated with a90309f4c014dfe6838838a844be1668249620db

A comment component should open up as a drawer. Recorded a video (on YouTube) to demonstrate the capability.

See Figma frames comment open and comment closed for a design candidate from @siarhei (our designer).

My thinking is that a third pane (to the right), like an aside could function like a side-notes/aside/footnotes section where we can present the comments (however long they are). This would keep the flow of the main text clean. In this case, we would just show some line in the main Prose view to indicate that there is some content hidden away and then the user can click on some icon on that line (like the plus or expand icon) to open the full comment block in the third and right-most pane -- the aside.

DONE
Integrate Comment component
@vidbina
- State "DONE"       from "IN_TEST"    [2023-01-05 Thu 21:19] \\
  Already in mainline for a while now and cleaned up as per 90ad707327877f3fab6aef7bf89f8818d8a39d42

Take the component that @tijan developed and wire it up to replace the FallbackBlocks where we need comments displayed.

DONE
Design a mechanism to bulk multiple successive comments into a single block
@vidbina
- State "DONE"       from "TODO"       [2023-01-03 Tue 16:32] \\
  In mainline already (by Tijan)

Currently all comments are rendered in individual blocks, but we really want multiple comments to be presented under a single disclosure that can render multiple comments when expanded.

CANCELLED
Trigger Disclosure toggle on title click
@tijan
- State "CANCELLED"  from "TODO"       [2023-01-05 Thu 21:20] \\
  Latest implementation 90ad707327877f3fab6aef7bf89f8818d8a39d42 involved a right-aligned comment icon which lacks a title text so this point is hereby rendered moot

The left-most expand/collapse icon is rather tiny and annoying to hit when in a hurry. As a user, I want to be able to quickly expand/collapse a comment block by clicking on the title too.

DONE

Implement Source Blocks

@vidbina
- State "DONE"       from "TODO"       [2022-09-29 Thu 16:42] \\
  Implemented by rendering source in a fallback component since https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/96. Future work will be to render this in a slicker code component. Battle for another day tho.

As a reader, I want to see the contents of source blocks presented as code. We don't expect any highlighting or any nifty features but we simply want to be able to read the contents of the code blocks.

We should be able to read the source block in section Parse block comments which is currently hidden.

The following code block should be parsed and displayed correctly (open as plaintext just to see what is in the source block).

#+begin_src txt
This is a code-block inside of a an Org source block
#+end_src
describe('source block', () => {
  const dut = (x) => parse(x).content[0]

  it('parses', () => {
    const raw = `
#+begin_src txt
.......
. .   .
.......
#+end_src
`
    expect(dut(raw)).toMatchInlineSnapshot(`
        {
          "content": ".......
        . .   .
        .......
        ",
          "type": "{",
        }
      `)
  })
})
TODO

[83%] Implement Org tables

DONE
Stub table component
@tijan
- State "DONE"       from "TODO"       [2022-09-15 Thu 12:53] \\
  Looking good and merged into hack [2022-09-15 Thu 12:53].
DONE
Render table in fallback while we await a proper implementation
@vidbina
- State "DONE"       from "TODO"       [2022-09-29 Thu 16:53] \\
  Wrote this down and realized the table renders in a fallback-like style. Good enough for now.

We can't wait forever on this one, so meanwhile we need a way to render the following table in a fallback component and then touch it up into a slicker representation at a later point:

keyvalue
nameformation.tools
typedevtool
stageprototype
current nichethat Emacs crowd
eventual goal
DONE
Parse tables
@vidbina
- State "DONE"       from "WIP"        [2023-01-11 Wed 16:35] \\
  Merged with 4ed244fa0f0e6abbe12cd627d57569eb8bed2d3d

In order to display tables, we will need to parse them first. 😅 Right now the underlying datastructure is completely unclear (although I do have some ideas). Implementing the parsing of tables will inform which attributes and properties we need to keep in consideration.

Refer to previous task with example table for some example data to work with.

Here is an example table that lists some berries -- yes berries 🍓.

NameGerman nameCaloriesCarbohydrates (grams)Protein (grams)Fat (grams)FiberSodium (grams)Potassium (grams)
AvocadoAvocado2401332210.011
BananaBanane11028103.450
PumpkinKurbis137710.1710.340
CucumberGurke8
DONE
Integrate table component
@vidbina
- State "DONE"       from "TODO"       [2023-01-11 Wed 16:36] \\
  Merged with 4ed244fa0f0e6abbe12cd627d57569eb8bed2d3d
DONE
Limit table height
@tijan
- State "DONE"       from "IN_TEST"    [2023-01-19 Thu 15:47] \\
  Was altered along with tijan/table-pane-functionality but probably in mainline before that already

Now that tables are implemented, you'll notice that tables are sometimes to long and too wide. Limit the table height in the same way we limit a code block's height such that it never completely takes over the screen.

Here is a large table to test with:

SolutionPlaintextOfflineCollaborationGitProseProductivityAutomationLicenseKiller featureTotal ScoreMissing featureComment
Amie
AFFiNE1111MITblock-like as in Notion
Quatro1GPL2
Outline1BUSL 1.1
Acreom11011
Archbee010Org-capabilities (tasks, planning, productivity)
Notion01mobile-firstnessopenness (proprietary formats, complex API with block as primitive entity)block-based, team-focussed but many don't use it in teams, bought cron
Confluence01Jiraopenness (API is horrible, centralized)
Fibery
Org Mode (in Emacs)111Emacsinaccessible to non-Emacs users, too flexible when you start tinkering with elisp
Etherpad101010Apache 2.0
LogSeq1110💡 Possible base for a non-Emacs client
Workflowy0
TiddlyWiki
HedgeDoc11
Linear
Obsidian11💡 Possible base for a non-Emacs client
Roam Research11
ClickUp
RemNote11
Jira01
Coda1
Thymer1
Clover1
Basecamp
Organice
Orgzly
GitHub Projects
GitLab Projects
GitBook
Pivotal Tracker
Open Project
Shortcut
Awork
Notesnook (see HN)
Tana
Tyles
Vistaly
Standard Notes
iA Writer
zube.io
spreadsheet.comfound about from @ImpostorEngineer mid-stream
OneNote
Totango (CS tool)
IN TEST
Provide zoom facility to show table in full-viewport mode
@tijan

As a user, I want to be able to expand a table to fill my entire working area. In this setup the table would assume as much space as the Kanban board assumes.

We need to provide some mechanism to click a "arrows-pointing-out" (heroicons) button that the end user can close again to return to the Prose view.

When pressing expand, we need to present a new pane (to the right of the current pane in which the item resides which we want to expand). This new pane should be closable.

DONE

Introduce some padding in the ToC (left and right) to render it less crowded

@tijan
- State "DONE"       from "TODO"       [2022-09-14 Wed 11:15] \\
  Already implemented and live.

The current ToC is looking very cluttered. Let's show the TODO tag, the headline text (for majority of the width of the ToC pane) and then the tags. I'm also open to dropping the tags from the TOC just to keep things cleaner because I believe that this is very likely just too much information.

CANCELLED

Implement general wrapper for inline components

@tijandebt
- State "CANCELLED"  from "TODO"       [2023-01-06 Fri 14:49] \\
  This is a very old point that is moot at the moment since we have different abstractions in place.

Grep codebase for @tijan and you'll find some notes on our Tailwind usage and DRY-ness (DRY as in "don't repeat yourself"). Let's stub an InlineContainer and a BlockContainer which we can reuse without having to redefine borders, shadows, background colors and basic typography.

Spoke with @tijan about this and we can look at extracting classes the Tailwind way https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply to minimize duplication.

For now we have a Block element that also exposes blockClasses in case we need block-like styling anywhere but this point is still outstanding for refactoring.

WIP

Implement comment component

@tijan

[50%] Kanban Perspective

DONE

Make Kanban columns scrollable

@edris
- State "DONE"       from "TODO"       [2022-11-25 Fri 10:50] \\
  Just merged with fc45bdaeff3ba100964e8b5ab08ab54da07a34a7

Currently the entire Kanban view is y-scrolled as a whole but we want end-user to scroll individual columns for better control. Especially alter when we will want to facilitate DnD.

IN SCOPING

Stub capability to nest Kanban cards under a parent

@edris@tijan

This probably requires some table-like approach in order to produce proper column spanning wrappers.

TODO

Bug: On Safari, Kanban cards sometimes show up with a dark background

@tijan
DONE

Clean up Kanban cards component

@vidbina
- State "DONE"       from "TODO"       [2022-09-07 Wed 21:53] \\
  More or less done, albeit scrappy 😅

[100%] Lists

DONE

Fix typography in lists

@stefano
- State "DONE"       from "IN_TEST"    [2023-01-03 Tue 16:43]
- State "IN_TEST"    from "TODO"       [2022-12-23 Fri 21:35] \\
  Merged into mainline after a fix by Tijan. Just moving to test as I'd like to give it some time to see what emerges. Any checks conducted so far suggest that both typography and disc/bullet weirdness are resolved now.

Text is lists is typeset differently to the main text which should not be the case. All text in lists should be rendered in the same size as other prose.

Perhaps there is a text-sm or something of the sort somewhere in the tree of the list that needs removing.

Furthermore, the discs in lists are broken in the mobile view. The alignment of the bullet or disc seems to move vertically as a list is expanded and collapsed.

DONE

Display checkboxes in lists

@stefano
- State "DONE"       from "IN_DEV"     [2023-01-06 Fri 15:09] \\
  Merged with 4b53d958950d1c231fac33b9aff155202f05d1dc

Currently lists are not displaying checkboxes. Here is a snippet to test things with in case you want to use it in a Storybook or so. Mind you that FListItem supports the following values for checkbox: on, off and trans which is what you'll need to test this.

- [ ] this should start with a checkbox
- this should not start with a checkbox
- we can also do this with nested lists
  - [ ] with
  - without
  - [X] with and checked
  - [-] with and in trans mode
+ [-] funny :: what did the hacker say to the librarian?

See branch vidbina.prep/stefano/display_checkboxes where I have already retrofitted ListItem to be checkbox aware so you don't have to worry about the parser/renderer logic behind the scenes.

Transitive state

Not sure if transitive is what trans actually stands for but let's just pretend.

The snippet:

- [X] done
- [-] partially done
  - [ ] not because the first child is marked done
  - [X] but because the second one is
- [ ] not done
- [X] a task item with children is fully done when
  - [X] all
  - [X] of
  - [X] its
  - [X] children
  - [X] are
  - [X] done
- luckily we don't have so sort out that case in the front-end. The parser should figure out how to calculate the trans state of a task with multiple children

will produce the following list (which should render correctly once the implementation is complete):

Note that the trans state is informed by the state of the children tasks with the following cases:

Indeterminate State

Here is some documentation on the indeterminate state available in standard checkboxes https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#indeterminate_state_checkboxes. Let this be our guide.


comments

Tailwind does provides some styling for indeterminate states which I have posted in a Slack thread as https://asabina.slack.com/archives/C036C60HWQP/p1672774272401549?thread_ts=1672699828.406419&cid=C036C60HWQP

DONE

Implement definition lists

@stefano
- State "DONE"       from "WIP"        [2023-02-13 Mon 17:40] \\
  Already implemented by Stefano and merged for a while so we consider this sorted.

Definitions in definition lists are not rendered atm. The following snippet:

- Apple Computer :: a computer company
- Apple Records :: record label
- Grannie Smith :: green apple

Should render a definition list (see mdn) when this task is completed.

Let's start with a single line per entry where the term is either boldfaced or wrapped in a light-gray button-like frame and the definition itself is just regular text.

DONE

Implement ordered lists

@stefano

The following list types are supported:

The order in which we're implementing them are:

Where:

If all tasks are completed, we should be able to look at this task and see all the lists correctly rendered as is to be expected.

The raw text of the task is listed below such that you can at least read the task even while some parts of the content are not yet implemented in formation.tools:

The following list types are supported:
- unordered
- ordered
- definition list

The order in which we're implementing them are:
1. unordered
2. definition list
3. ordered

Where:
- unordered lists :: lists with bullets
- ordered lists :: lists that are numbered
- definition list :: list like there where /terms/ are paired/matched with a /definition/

If all tasks are completed, we should be able to look at this task and see all the lists correctly rendered as is to be expected.
DONE

Parse list item tag

@vidbina
- State "DONE"       from "WIP"        [2023-02-13 Mon 17:42]

Looking at Display checkboxes in lists, we still need to parse tags inside of list items. Not sure if we already have support for this in uniorg or if we'll have to implement it and post a PR. 🤷🏿‍♂️

DONE

Implement list parsing

@vidbina
- State "DONE"       from "TODO"       [2022-09-05 Mon 22:33] \\
  Implemented with vidbina/parse-lists, ready for @tijan to work on the component.

List can be parsed as follows:

import parse from core/parser'

parse(rawText).content[0]

where you can use the following raw text samples:

💡 All of the previously listed samples are verified to parse correctly in the parser spec (core/parser.test.ts).
DONE

Implement list component

@tijan
- State "DONE"       from "TODO"       [2022-09-14 Wed 11:42] \\
  Merged into mainline but the question of folding/unfolding lists is yet to be solved.

In order to render lists correctly, we need to stub out a List component that can handle the inputs demonstated in Implement list parsing.

DONE

Implement list folding

@stefano
- State "DONE"       from "TODO"       [2022-12-07 Wed 09:30] \\
  Merged with b3f857e2a3a319b2014c4a2677e0ba5733259504

Use a Disclosure to facilitate this. As Disclosures have been used in multiple places throughout the codebase, grepping for those examples may provide clues on how to implement this.

DONE

Fix list transition dimensioning bug

bug
- State "DONE"       from "TODO"       [2022-12-07 Wed 16:57] \\
  Resolved by using headlessui's Disclosure

Lists crop their content which is very likely to be attributed to the way CSS transitions are implemented.

export function ListChild({
  label,
  children,
}: PropsWithChildren<ListChildProps>) {
  const [showChildren, setShowChildren] = useState(true)

  const animation =
    '[&>div]:overflow-hidden [&>div]:transition-[max-height] [&>div]:duration-100 [&>div]:ease-in-out'

  const itemClasses = [
    'relative h-fit',
    showChildren
      ? `[&>div]:max-h-screen ${animation}`
      : `[&>div]:max-h-0 ${animation} [&>p]:hidden [&>p:first-child]:block`,
      //...
    ]
}

Formats

Org

TODO
Stub helper to detect which workflowstates are terminals
@vidbina

In order to determine which sections to fold by default, we need to figure out what the terminal workflow states for a document are. This helper should default to treating DONE and CANCELED are defaults if a document does not register any workflows in order to capture the terminals that are defined by org-elements as default endingin workflow states.

Markdown

DONE

Stub NarrowSidebar layout for reader view

@vidbina
- State "DONE"       from "IN_DEV"     [2023-01-03 Tue 16:44]
- Note taken on [2022-09-05 Mon 22:30] \\
  Just wired up the home page to display the Engineering doc with branch vidbina/wire-up-layouts. Consider this a babystep to the end-goal.

Page reader[url] will be using the NarrowSidebar which is already demonstrated in a story for reference's sake. The following inputs are needed for the new layout:

TODO

[30%] Dev Tooling

devtools
:COOKIE_DATA: todo recursive

[20%] Automated Testing

devtoolsqa
TODO
Add test stage to Vercel pipeline
@jamba

As a developer, I sometimes catch snapshot breakage when I'm trying to work on a new feature and this should be caught much earlier by the build pipelines.

Failures in test should not be discovered by developers but should be discovered by the build pipelines.

⚠️ The current =hack= branch now contains a gitlab CI pipeline that runs in parallel to the external Vercel job. Let's figure out if we:

1. delay the Vercel job until the test stage in the GitLab CI pipeline passes. That way we don't waste compute on Vercel if the test pipeline fails and we block deploying code that has failing tests. I don't know if this is possible since this job is an external one and perhaps it is hard to influence it.

2. If idea 1 is too tricky, we can setup the Vercel token inside of Gitlab CI and build and deploy the app directly from GitLab CI (as opposed to from Vercel through an external job).

Open to ideas here though especially compelling cons for either of the approaches.
IN TEST
Setup Playwright to dev tooling
@jamba

As a team, we need to have some tooling in place for E2E testing. Better to set this up sooner rather than later such that we can already start stubbing the first E2E cases to minimize the cost of manual click-through during development.

The first test case, should complete the following steps:

TODO
Add E2E test suite to GitLab CI pipeline
@jamba

As devs, we want E2E tests to automatically get run in a pipeline. Ideally, we have a way to obtain visual feedback from the pipeline as well.

Not sure if the GitLab CI runners are enough for this or if there is a service where we can run these test workloads (also on Safari, which would require a macOS environment which I think GitLab also offers so my gut tells me that GitLab CI should be up to the task). Perhaps we may have to opt for something like BrowserStack or https://www.lambdatest.com/ (see https://www.lambdatest.com/support/docs/playwright-tests-in-ci-cd/ for the CI/CD part and https://www.lambdatest.com/support/docs/gitlab-ci-integration-with-lambdatest/ for the Gitlab CI bit).

If we can extend GitLab CI to run the E2E suite let's do so! Otherwise, we need to get accounts setup at the service to try and adapt the GitLab CI pipeline to get this to work (if adaptation of the pipeline is even necessary).

Explore the different options (perhaps even my testing the tooling on test repos) to help us figure out how to best set either of these up for this project.

DONE
Setup coverage tracking
@vidbina

Setup Codecov for project because it is a FLOSS-friendly option so we'd happily give them our money.

See https://docs.codecov.com/docs/gitlab-tutorial for implementation details

TODO
Fix Codecov reporting

The https://app.codecov.io/gitlab/formation.tools:eng/proto-01 page is not listing our coverage (it is only listed by going to commit-specific pages). My hunch is that codecov is having some trouble cataloging our coverage data because of our merging workflow which heavily uses fast-forward merges.

See @vidbina Tweet to @codecov for a different phrasing of the issue as I observed it then.

Merging Workflow

We have a main branch which is deploys to production and a hack branch which deploys to staging.

We merge feature branches to hack (staging) and when this is done in some forge like GitLab (in our case) or GitHub, it a non-fast-forward merge into hack is made which will trigger a deployment to staging.

We maintain a single line between hack (staging) and main (production) so main is trailing hack until we decided that we can fast-forward its position. This means that we don't have unique revs for every event but often find our hack and main branches sharing the exact same point on the graph when everything is caught up.

Here is a visual breakdown:

         main     hack
          |        |
mainline  o--o--o--o
                    \
feature              o----o <- HEAD of feature branch

Such a merge results into the following situation (note how the feature branch was merged into hack).

         main              hack
          |                 |
mainline  o--o--o--o--------o--
                    \      /
feature              o----o

On a day-to-day basis, however; I don't always use GitLab's merge button to trigger merges but I may, start a WIP branch on my machine (actually called vidbina/merge.hack for me as I prefix all my merge-related branches with vidbina/merge. but WIP is shorter for the purpose of this description) starting from the upstream hack and then perform a non-fast-forward merge (like the forges do) locally. This workflow allows me to resolve conflicts more conveniently and run some tests/experiments thereafter.

I may throwaway these local WIP branches if I mess things up or want to approach the merge slightly differently.

         main     hack     WIP
          |        |        |
mainline  o--o--o--o--------o--
                    \      /
feature              o----o

Anyways, after confirming that the results are okay, I fast-foward merge (using git merge --ff) WIP into hack such that they share the same rev and then I push hack upstream.

                           hack
         main              WIP
          |                 |
mainline  o--o--o--o--------o--
                    \      /
feature              o----o

After the staging build has been out there without too much trouble, we catch up main through a fast-forward merge.

                           main
                           hack
                           WIP
                            |
mainline  o--o--o--o--------o--
                    \      /
feature              o----o
TODO
Refile Merging Workflow out of the task

Once the task is done and considering that the merging workflow write-up is not too shabby, we should file it were devs can reference it more easily (like in the proto repo itself).

TODO

Fix broken Mock Board

storybook

The storybook at http://localhost:6006/?path=/story/modes-board-organisms-kanbanspace--mock-board does not update when the text is updated unless one navigates away from the story and back into it.

TODO

Setup Storybook to be Next Router aware

devtools
TODO

Upgrade Storybook

devtoolsdebt

See the following snippet:

╭──────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                                          │
│   Storybook 6.5.10 for React started                                                     │
│   19 s for manager and 21 s for preview                                                  │
│                                                                                          │
│    Local:            http://localhost:6006/                                              │
│    On your network:  http://192.168.228.210:6006/                                        │
│                                                                                          │
│   A new version (6.5.12) is available!                                                   │
│                                                                                          │
│   Upgrade now: npx storybook@latest upgrade                                              │
│                                                                                          │
│   Read full changelog: https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md   │
│                                                                                          │
╰──────────────────────────────────────────────────────────────────────────────────────────╯
DONE

Remove base64encode from codebase or mock

fixdevtools
- State "DONE"       from "TODO"       [2022-09-29 Thu 16:40] \\
  Just merged into Hack as part of wrapping up https://staging.formation.tools/#implement-source-blocks (https://gitlab.com/formation.tools/eng/proto-01/-/merge_requests/96)

The use of base64encode Causes Buffer-related errors within storybooks and other more limited environments (iirc unit tests may be struggling with this as well but I could be wrong here) than the browser or Node.js:

index.js:56 Unexpected error while loading ./app/LayoutNarrowSidebar.stories.tsx: Buffer is not defined
 ReferenceError: Buffer is not defined
    at Function.encode (http://localhost:6006/vendors-node_modules_storybook_addon-actions_preview_js-generated-config-entry_js-node_module-9a87b3.iframe.bundle.js:31241:5)
    at encodeTarget (http://localhost:6006/main.iframe.bundle.js:4472:59)
    at Module../core/helpers.tsx (http://localhost:6006/main.iframe.bundle.js:4470:21)
    at __webpack_require__ (http://localhost:6006/runtime~main.iframe.bundle.js:28:33)
    at fn (http://localhost:6006/runtime~main.iframe.bundle.js:339:21)
    at Module../components/app/LayoutNarrowSidebar.tsx (http://localhost:6006/main.iframe.bundle.js:2227:71)
    at __webpack_require__ (http://localhost:6006/runtime~main.iframe.bundle.js:28:33)
    at fn (http://localhost:6006/runtime~main.iframe.bundle.js:339:21)
    at Module../components/app/LayoutNarrowSidebar.stories.tsx (http://localhost:6006/main.iframe.bundle.js:5623:79)
    at __webpack_require__ (http://localhost:6006/runtime~main.iframe.bundle.js:28:33)
error @ index.js:56
(anonymous) @ executeLoadable.js:58
(anonymous) @ executeLoadable.js:52
executeLoadable @ executeLoadable.js:51
executeLoadableForChanges @ executeLoadable.js:100
getProjectAnnotations @ start.js:129
configure @ start.js:165
configure @ index.js:21
./generated-stories-entry.cjs @ generated-stories-entry.cjs:6
__webpack_require__ @ bootstrap:24
_requireSelf @ hot module replacement:102
apply @ jsonp chunk loading:444
(anonymous) @ hot module replacement:344
internalApply @ hot module replacement:342
hotApply @ hot module replacement:301
cb @ process-update.js:76
(anonymous) @ process-update.js:91
Promise.then (async)
check @ process-update.js:90
module.exports @ process-update.js:52
processMessage @ client.js:279
handleMessage @ client.js:139
handleMessage @ client.js:102
react-dom.development.js:86 Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

We can either

CANCELLED

Setup stories to point towards a few real raw Org files

@tijan
- State "CANCELLED"  from "TODO"       [2022-11-23 Wed 06:58] \\
  This was not trivial to resolve, so we're parking this to perhaps revisit in the future. For now we'll just repeat Org content that is tailored to the component of interest.

In order to simplify development and to avoid us having to switch between storybook tabs and dev page tabs, it would be nice to have a story for Prose and Board where the content is the raw README file that we are displaying on the home page right now.

[50%] TODO Organize components into an atomic design system

@stefano
IN TEST
Configure for Storybook deployment to Chromatic
@stefano

The objective is to have Storybook's publically accessible such that have a quick reference to use in conversations (on any channel). Sharing links around will make "talking about things" a bit easier.

Some use Netlify to deploy their Storybooks. For us it doesn't matter where we host these as long as it allows for public access and it a moderately friendly (ask me what this means over a beer 🍺) platform/tool.

DONE
Define new component file tree or taxonomy
@stefano
- State "DONE"       from "TODO"       [2022-11-25 Fri 10:53] \\
  Stefano has largely done the gruntwork. Now we test this out and find out over time if the taxonomy needs changes. If no issues arise over the next months, we can concretize this design by renaming all associated artifacts to reflect the naming scheme.

We have a bunch of components now and considering that this will grow going forward, it is a good moment to organize our components structure a bit better.

Look into atomic design for some guidance/ideas on how we can structure our components. We may already be "redefining" components (that may be atoms) in multiple places since it isn't always too clear what may already be there.

Update title fields in the Storybook stories to suggest a new taxonomy that breaks our component structure down into:

Chapter 2 of the Atomic Design book provides some guidance on what these taxons mean.

Some brainfarts on what triggered this task:

[44%] Cleanup

:COOKIE_DATA: todo recursive
TODO

Investigate validity of parse() calls within components

There is one case in Comments where we directly call parse() inside the component. We typically shouldn't ever have to do that.


comments

Inside of storybooks and tests such calls are okay as we're trying to simplify the generating of those payloads that we can render whatever ReactNode-like data we need to add to our components to see it at work.

Instead of having to explicitly list intermediate representation or verbatim HTML or JSX, we just type the Org (which is easier to read for a person) and then rely on the parser to provide the data structure that we can feed to our renderer.

Other uses of parse() in non-test and non-storybook cases, should be limited.

TODO

[60%] Resolve NextJS warnings

Just had a call with Tijan where we spoke about the following issues

DONE
Resolve ResizableBox warnings
@tijan
- State "DONE"       from "TODO"       [2023-01-05 Thu 18:14] \\
  Resolved with d2bc92148499379ead6b82cc62ad5b626e5f1a08

Observe the following warnings:

 next-dev.js?3515:24 Warning: Failed prop type: The prop `height` is marked as required in `ResizableBox`, but its value is `undefined`.
    at ResizableBox (webpack-internal:///./node_modules/react-resizable/build/ResizableBox.js:46:35)
    at ResizablePane (webpack-internal:///./components/app/ResizablePane.tsx:12:32)
    at main
    at HorizontalDiptychWithAside (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:627:22)
    at div
    at div
    at Layout (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:828:22)
    at HomePage (webpack-internal:///./pages/index.tsx:46:21)
    at SessionContextProvider (webpack-internal:///./node_modules/@supabase/auth-helpers-react/dist/index.js:42:3)
    at MyApp (webpack-internal:///./pages/_app.tsx:30:27)
    at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:20740)
    at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:23199)
    at Container (webpack-internal:///./node_modules/next/dist/client/index.js:149:9)
    at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:652:26)
    at Root (webpack-internal:///./node_modules/next/dist/client/index.js:774:27)
next-dev.js?3515:24 Warning: Failed prop type: The prop `height` is marked as required in `Resizable`, but its value is `undefined`.
    at Resizable (webpack-internal:///./node_modules/react-resizable/build/Resizable.js:46:35)
    at ResizableBox (webpack-internal:///./node_modules/react-resizable/build/ResizableBox.js:46:35)
    at ResizablePane (webpack-internal:///./components/app/ResizablePane.tsx:12:32)
    at main
    at HorizontalDiptychWithAside (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:627:22)
    at div
    at div
    at Layout (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:828:22)
    at HomePage (webpack-internal:///./pages/index.tsx:46:21)
    at SessionContextProvider (webpack-internal:///./node_modules/@supabase/auth-helpers-react/dist/index.js:42:3)
    at MyApp (webpack-internal:///./pages/_app.tsx:30:27)
    at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:20740)
    at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:23199)
    at Container (webpack-internal:///./node_modules/next/dist/client/index.js:149:9)
    at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:652:26)
    at Root (webpack-internal:///./node_modules/next/dist/client/index.js:774:27)
TODO
Resolve react hydration issue on ToC className
@vidbina
Warning: Prop `className` did not match. Server: "transition-all fill-black  h-4 w-4 cursor-pointer select-none" Client: "transition-all fill-white  h-4 w-4 cursor-pointer select-none"
    at svg
    at ChevronDownIcon
    at span
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:3918)
    at div
    at li
    at C (webpack-internal:///./node_modules/@headlessui/react/dist/internal/open-closed.js:8:255)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:1808)
    at TableOfContentsEntry (webpack-internal:///./components/app/TOC.tsx:29:24)
    at ul
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:5848)
    at div
    at C (webpack-internal:///./node_modules/@headlessui/react/dist/internal/open-closed.js:8:255)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/transitions/transition.js:18:2533)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/transitions/transition.js:18:5475)
    at li
    at C (webpack-internal:///./node_modules/@headlessui/react/dist/internal/open-closed.js:8:255)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:1808)
    at TableOfContentsEntry (webpack-internal:///./components/app/TOC.tsx:29:24)
    at ul
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:5848)
    at div
    at C (webpack-internal:///./node_modules/@headlessui/react/dist/internal/open-closed.js:8:255)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/transitions/transition.js:18:2533)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/transitions/transition.js:18:5475)
    at li
    at C (webpack-internal:///./node_modules/@headlessui/react/dist/internal/open-closed.js:8:255)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:1808)
    at TableOfContentsEntry (webpack-internal:///./components/app/TOC.tsx:29:24)
    at ul
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:5848)
    at div
    at C (webpack-internal:///./node_modules/@headlessui/react/dist/internal/open-closed.js:8:255)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/transitions/transition.js:18:2533)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/transitions/transition.js:18:5475)
    at li
    at C (webpack-internal:///./node_modules/@headlessui/react/dist/internal/open-closed.js:8:255)
    at eval (webpack-internal:///./node_modules/@headlessui/react/dist/components/disclosure/disclosure.js:16:1808)
    at TableOfContentsEntry (webpack-internal:///./components/app/TOC.tsx:29:24)
    at ul
    at TOC (webpack-internal:///./components/app/TOC.tsx:185:26)
    at div
    at aside
    at div
    at Resizable (webpack-internal:///./node_modules/react-resizable/build/Resizable.js:46:35)
    at ResizableBox (webpack-internal:///./node_modules/react-resizable/build/ResizableBox.js:46:35)
    at ResizablePane (webpack-internal:///./components/app/ResizablePane.tsx:12:32)
    at main
    at HorizontalDiptychWithAside (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:627:22)
    at div
    at div
    at Layout (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:828:22)
    at HomePage (webpack-internal:///./pages/index.tsx:46:21)
    at SessionContextProvider (webpack-internal:///./node_modules/@supabase/auth-helpers-react/dist/index.js:42:3)
    at MyApp (webpack-internal:///./pages/_app.tsx:30:27)
    at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:20740)
    at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:23199)
    at Container (webpack-internal:///./node_modules/next/dist/client/index.js:149:9)
    at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:652:26)
    at Root (webpack-internal:///./node_modules/next/dist/client/index.js:774:27) 

See more info here: https://nextjs.org/docs/messages/react-hydration-error
DONE
Resolve key issue on CommentsBlock
@tijan
- State "DONE"       from "TODO"       [2023-01-05 Thu 18:15] \\
  Merged with 5277b63b6f06e045defe8226203c30f198444e36
next-dev.js?3515:24 Warning: Each child in a list should have a unique "key" prop.

Check the render method of `RenderCommentHelper`. See https://reactjs.org/link/warning-keys for more information.
    at CommentsBlock (webpack-internal:///./components/doc/Comment.tsx:42:20)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:16:25)
    at div
    at section
    at Section (webpack-internal:///./components/doc/Section.tsx:21:21)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:16:25)
    at div
    at section
    at Section (webpack-internal:///./components/doc/Section.tsx:21:21)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:16:25)
    at div
    at section
    at Section (webpack-internal:///./components/doc/Section.tsx:21:21)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:16:25)
    at div
    at Prose (webpack-internal:///./components/mode/Prose/index.tsx:13:25)
    at div
    at section
    at main
    at HorizontalDiptychWithAside (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:627:22)
    at div
    at div
    at Layout (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:828:22)
    at HomePage (webpack-internal:///./pages/index.tsx:46:21)
    at SessionContextProvider (webpack-internal:///./node_modules/@supabase/auth-helpers-react/dist/index.js:42:3)
    at MyApp (webpack-internal:///./pages/_app.tsx:30:27)
    at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:20740)
    at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:23199)
    at Container (webpack-internal:///./node_modules/next/dist/client/index.js:149:9)
    at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:652:26)
    at Root (webpack-internal:///./node_modules/next/dist/client/index.js:774:27)
window.console.error	@	next-dev.js?3515:24
printWarning	@	react-jsx-dev-runtim…elopment.js?17e1:87
error	@	react-jsx-dev-runtim…elopment.js?17e1:61
validateExplicitKey	@	react-jsx-dev-runtim…opment.js?17e1:1078
validateChildKeys	@	react-jsx-dev-runtim…opment.js?17e1:1105
jsxWithValidation	@	react-jsx-dev-runtim…opment.js?17e1:1276
RenderCommentHelper	@	VM98527 RenderCommentHelper.tsx:22
renderWithHooks	@	react-dom.development.js?ac89:16305
mountIndeterminateComponent	@	react-dom.development.js?ac89:20074
beginWork	@	react-dom.development.js?ac89:21587
beginWork$1	@	react-dom.development.js?ac89:27426
performUnitOfWork	@	react-dom.development.js?ac89:26557
workLoopSync	@	react-dom.development.js?ac89:26466
renderRootSync	@	react-dom.development.js?ac89:26434
performConcurrentWorkOnRoot	@	react-dom.development.js?ac89:25738
workLoop	@	scheduler.development.js?bcd2:266
flushWork	@	scheduler.development.js?bcd2:239
performWorkUntilDeadline	@	scheduler.development.js?bcd2:533
DONE
Resolve missing onChange handler on form field
stefano
- State "DONE"       from "TODO"       [2023-01-05 Thu 18:13] \\
  Merged into mainline with 4de4147405ba68068095acad442196906de3a90b

Probably just set readOnly for now.

Warning: You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.
    at input
    at span
    at ListChildLabel (webpack-internal:///./components/doc/List.tsx:21:27)
    at li
    at ListChild (webpack-internal:///./components/doc/List.tsx:72:22)
    at ul
    at List (webpack-internal:///./components/doc/List.tsx:54:17)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:21:32)
    at div
    at section
    at Section (webpack-internal:///./components/doc/Section.tsx:26:20)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:21:32)
    at div
    at section
    at Section (webpack-internal:///./components/doc/Section.tsx:26:20)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:21:32)
    at div
    at section
    at Section (webpack-internal:///./components/doc/Section.tsx:26:20)
    at RenderCommentHelper (webpack-internal:///./utils/RenderCommentHelper.tsx:21:32)
    at div
    at Prose (webpack-internal:///./components/mode/Prose/index.tsx:16:18)
    at div
    at section
    at main
    at HorizontalDiptychWithAside (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:575:39)
    at div
    at div
    at Layout (webpack-internal:///./components/app/LayoutNarrowSidebar.tsx:770:19)
    at HomePage (webpack-internal:///./pages/index.tsx:46:21)
    at SessionContextProvider (/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@supabase/auth-helpers-react/dist/index.js:42:3)
    at MyApp (webpack-internal:///./pages/_app.tsx:26:18)
    at StyleRegistry (/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/styled-jsx/dist/index/index.js:671:34)
    at AppContainer (/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/next/dist/server/render.js:404:29)
    at AppContainerWithIsomorphicFiberStructure (/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/next/dist/server/render.js:433:57)
    at div
    at Body (/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/next/dist/server/render.js:690:21)
TODO
Resolve data for page exceeding threshold
Warning: data for page "/" is 346 kB which exceeds the threshold of 128 kB, this amount of data can reduce performance.
See more info here: https://nextjs.org/docs/messages/large-page-data
DONE

Use Image instead of img to resolve warning

@stefano
- State "DONE"       from "TODO"       [2023-01-03 Tue 16:57] \\
  Already in mainline. Thanks to Stefano and commit 9d229f2289d6d2c8dd76e8a44ee93cbe16ee67ca

The following warnings pop up when building the project:

./components/Board/EditTaskModal.tsx
58:17  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
77:17  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
96:17  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
187:15  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element

./components/Board/Task.tsx
68:17  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
95:27  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element

./components/app/LayoutExample.tsx
102:23  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
140:27  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
173:19  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
211:23  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
235:17  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element

./components/app/LayoutMultiColumn.tsx
98:23  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
166:29  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
257:27  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
524:25  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element

./components/app/LayoutSidebar.tsx
117:21  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
164:15  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element
246:23  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element

./components/app/Menu.tsx
34:5  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element

./components/app/NavigationBar.tsx
154:19  Warning: Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element  @next/next/no-img-element

info  - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
info  - Linting and checking validity of types ..Failed to compile.

The fix should be pretty trivial so it's a quick win. 🏆

WIP

[80%] Replace Grommet for TailwindCSS

debt
DONE
Setup TailwindCSS
- State "DONE"       from "TODO"       [2023-01-03 Tue 16:58] \\
  Already done a while ago

Switching from Grommet to Tailwind because:

DONE
Setup Tailwind for Storybook
@assutech
- State "DONE"       from "TODO"       [2022-08-23 Tue 17:36] \\
  Sorted by @purcy on [2022-08-23 Tue] so we no longer have to worry about this. Future point would be to look into honoring Tailwind styles in the Storybook views as the current setup renders the components without any styling.

To simplify development of UI parts, we would like to be able to review components in Storybook. For this, we need to configure the project in order for npm run storybook.

Fix the configuration and provide links to the relevant documentation that explains the design choicese in that configuration.

The following error is produced when running npm run storybook:

info @storybook/react v6.5.9
info 
info => Loading presets
info Addon-docs: using MDX1
info => Using PostCSS preset with postcss@7.0.39
info => Using default Webpack5 setup
<i> [webpack-dev-middleware] wait until bundle finished
9% setup compilation DocGenPluginnode:internal/modules/cjs/loader:959
  throw err;
  ^

Error: Cannot find module 'webpack/lib/util/makeSerializable.js'
Require stack:
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react-docgen-typescript-plugin/dist/dependency.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react-docgen-typescript-plugin/dist/plugin.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react-docgen-typescript-plugin/dist/index.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react/dist/cjs/server/framework-preset-react-docs.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core-common/dist/cjs/presets.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core-common/dist/cjs/index.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core-server/dist/cjs/index.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core/dist/cjs/server.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core/server.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react/dist/cjs/server/index.js
- /home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react/bin/index.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:956:15)
    at Function.Module._load (node:internal/modules/cjs/loader:804:27)
    at Module.require (node:internal/modules/cjs/loader:1028:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react-docgen-typescript-plugin/dist/dependency.js:6:55)
    at Module._compile (node:internal/modules/cjs/loader:1126:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
    at Module.load (node:internal/modules/cjs/loader:1004:32)
    at Function.Module._load (node:internal/modules/cjs/loader:839:12)
    at Module.require (node:internal/modules/cjs/loader:1028:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react-docgen-typescript-plugin/dist/dependency.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react-docgen-typescript-plugin/dist/plugin.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react-docgen-typescript-plugin/dist/index.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react/dist/cjs/server/framework-preset-react-docs.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core-common/dist/cjs/presets.js',    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core-common/dist/cjs/index.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core-server/dist/cjs/index.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core/dist/cjs/server.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/core/server.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react/dist/cjs/server/index.js',
    '/home/vidbina/src/formation.tools/eng/proto-01/main/node_modules/@storybook/react/bin/index.js'
  ]
}
DONE
Explore if we need HeadlessUI
@vidbina
- State "DONE"       from "WIP"        [2022-08-23 Tue 17:37] \\
  We need HeadlessUI for the React components and some of the dynamic behavior associated with them (think Dialogs for Modals, Disclosures for accordion-like components, etc.). Some of the TailwindUI components seem to depend on this library and other third-party component libraries such as Flowbite 😠 (yeah, I'm not amused about this product ATM) seem to do the same.

In branch vidbina/setup-tailwind-headlessui, we are trying out incorporating HeadlessUI components in our setup. If this works, it may simplify building components in React that are based on top of TailwindCSS.

The HeadlessUI repository is pretty small, as in, only few components.

DONE
Explore what we need from Flowbite
@purcymarte
- State "DONE"       from "DONE"       [2023-01-03 Tue 16:59] \\
  We only took part of the Kanban experience and are building around it. DX (dev experience) was a PITA so I'm not keen to go back to use Flowbite unless it really presents a significant advantage in us moving faster.

Flowbite has a UI blocks (based on TailwindCSS) that we can build on such as:

We have to explore to which extend we need this and can bring this in.

If we start a branch e.g.: setup-tailwind-flowbite, start it from vidbina/setup-tailwind.

CANCELLED
Investigate how to set html/body-level classes at run-time
- State "CANCELLED"  from "TODO"       [2023-01-03 Tue 17:00] \\
  Not relevant for now, so parking. Recommendation for dark mode is to tell folks to use DarkReader meanwhile. I'm using it in Chromium and Firefox and it offers me enough control to have a more personalized dark experience. Our objective should be to provide a design that looks good enough when DarkReader is on.

The Next.js docs outline in https://nextjs.org/docs/advanced-features/custom-document how we can set html and body level classes from within the pages/_document.tsx file with the caveat that these are server-side rendered and therefore cannot support dynamic behavior (for example the use of event handlers such as onClick).

The blog post https://smnh.me/add-class-to-body-tag-in-nextjs outlines some ways to deal with html/body-level dark-mode settings which are dynamic in the sense that they are change during run-time and will need to be updated. It isn't quite clear if the instructions here are relevant at this moment so we will need to investigate what the issue here is.

The reason why this information is relevant is because some of the TailwindUI components such as https://tailwindui.com/components/application-ui/application-shells/multi-column will require the following updates to our template:

<html class="h-full bg-white">
<body class="h-full overflow-hidden">

The use of class bg-white is for non-dark-mode templates. Toggling dark mode will therefore require changes to the html and body classList at runtime in order to work adequately.

DONE
Decompose selected layout from components/Layout into its constituent parts
- State "DONE"       from "TODO"       [2023-01-03 Tue 17:02] \\
  This has been done in some shape or form. We've abstracted away a bunch thanks to an effort led by @stefano to define a component taxonomy that works for us (following some parts of the Atomic Design idea). Renaming effort has been confined to updating Storybook names to provide some recommendation of how we should be structuring our component landscape. More effort will be needed to actually rename files but not while a lot of component-work remains high-flux.

@vidbina has copied over a few Application UI/Application Shells from TailwindUI and has made the necessary translations from HTML to JSX just to have something that looks okay-ish as a starting point.

We now have to take these compositions, basically UI dumps, and then decompose them into the larger subparts such as (following are just an example):

Note that the example in components/Layout.tsx is not complete in that some of the animations are broken and state is lacking which is why menus or other state-dependent elements will not behave correctly. All of these capabilities will need to be implemented.

💡 As a reference, look at component ToggleDarkMode which represents a basic TailwindCSS component which was translated from the TailwindUI code listing and then retrofitted to contain the correct images and to behave as expected by implementing event handling and by binding state into the component.
DONE
Implement ToC
- State "DONE"       from "TODO"       [2022-09-25 Sun 14:37] \\
  Basic TOC is implemented. Some improvements like linking are still pending but that is to be considered future work.

As a user, I want a ToC (table of contents) or sidebar present in the interface such to:

DONE
Stub ToC
@purcy
- State "DONE"       from "TODO"       [2022-08-23 Tue 17:39] \\
  @purcy stubbed this component today [2022-08-23 Tue] and I just integrated it so we should be good to go. We still want to incorporate HeadlessUI's Disclosure components in order to facilitate folding but this is a nice-to-have that we can address later. First we have to address some higher-level layouting concerns because I just plopped the ToC on a page without much though or any grace. 😅
DONE
Make ToC dark-mode aware
@purcy
- State "DONE"       from "TODO"       [2022-09-25 Sun 14:36] \\
  This issue is actually unresolved pending because we've refactored the TOC to show in dark-mode for better contrast during the light-mode. In the current form, we are not exposing the dark-mode functionality to end-users and will be recommending the use of a plugin like DarkReader to have a computed browser-wide dark-mode instead of one explicitly designed by us.

Switching between light and dark mode with the ToC rendered doesn't really change the text color. The ToC text should follow the classes for the main text which is altered during light/dark mode transitions. Not sure which TailwindCSS classes need to be set.

DONE
Incorporate Disclosure components to enable folding of levels
- State "DONE"       from              [2022-09-25 Sun 14:34] \\
  Already merged into mainline (work done by @tijan)
- State "DONE"       from              [2022-09-25 Sun 14:34] \\
  Implemented a naive approach (unique link ids per session)

See Design headline linking strategy for a characterization of the headline labelling problem. Once we've resolved this, we should roll an implementation for the ToC (and also the Prose but that is another concern).

DONE
Build Tailwind components for doc
- State "DONE"       from "TODO"       [2023-01-03 Tue 17:03] \\
  Mostly sorted by previous decomposition/organization efforts
IN DEV
Remove Grommet-specific containers
@stefano

We still use Col, Row, Main, MainContent and AppContainer from components/View.tsx

I'm upgraded this task (instead of a child of the [[*Setup TailwindCSS][Setup TailwindCSS]] task it is now a sibling thereof) since it doesn't block any of the other tasks. We can therefore move along on the Storybook or TailwindCSS concerns without this affecting us at all. Having it here may allow @purcy to prototype things quickly and then we do the translation afterwards so I'm deprioritizing this as well by moving it to the bottom of the task list.
TODO
Remove all Grommet artifacts

With Tailwind coming in, we should remove gradually remove Grommet. It isn't clear where all Grommet dependencies are, in terms of files that are Grommet-related, but we would need to identify them and then rid them from the dependency (remove Grommet dependency from core components) and also clean up the dependency manifest (packages.json).

Here is a result of a grep for "grommet" on the repo which indicates which parts still need removing:

components/View.tsx:import { Box, BoxExtendedProps } from 'grommet'
components/doc/Code.tsx:// FIXME: Remove grommet remnants
components/doc/Code.tsx:import { Box, ThemeContext } from 'grommet'
components/generic/UIHeading.tsx:import { Heading as GrommetHeading } from 'grommet'
[...snipped results from package.json and package-lock.json...]
pages/r/index.tsx:import { Button, TextInput } from 'grommet'
↪ √ → ~/src/formation.tools/eng/proto-01/main @ 2023.02.13 17:45

Note that _app.tsx imported GlobalStyle from styles/global.js. We have already removed the import but the styles/global.js file is still in place and will need to be removed.

Note that a grep for "global" indicates that we use the Grommet styles in the following places:

.storybook/preview.js:import '../styles/globals.css'
[...snipped...]
pages/_app.tsx:import '../styles/globals.css'
pages/_app.tsx:      <style jsx global>{`
TODO

Replace uuidv4 with uuid

TODO

Merge unpackElementType and convert into single function

archdebt

Perhaps we even remove unpackElementType in order to fully rely on convert which we may rename to unpack in its new role.

The reasons being:

Background
The components of this syntax can be divided into two classes: “objects” and “elements”. To better understand these classes, consider the paragraph as a unit of measurement. Elements are syntactic components that exist at the same or greater scope than a paragraph, i.e. which could not be contained by a paragraph. Conversely, objects are syntactic components that exist with a smaller scope than a paragraph, and so can be contained within a paragraph.

Elements can be stratified into “headings”, “sections”, “greater elements”, and “lesser elements”, from broadest scope to narrowest. Along with objects, these sub-classes define categories of syntactic environments. Only headings, sections, property drawers, and planning lines are context-free1, 2, every other syntactic component only exists within specific environments. This is a core concept of the syntax.

Expanding on the stratification of elements, lesser elements are elements that cannot contain any other elements. As such, a paragraph is considered a lesser element. Greater elements can themselves contain greater elements or lesser elements. Sections contain both greater and lesser elements, and headings can contain a section and other headings.
TODO

Fix unpackElementType to return correct fallbacks

debt

The function unpackElementType returns an incorrect fallback. It returns a e-typed fallback, which is reserved for Element types, for a GreaterElement element which should actually unpack into an E-typed fallback.

Furthermore, there are a bunch of elements for which this function just returns nothing (denoted by the empty list) instead of a fallback entry so a bunch of information goes missing.

TODO

Rename FObjectType to FObject

debt

For naming consistency, we should drop the Type prefix. I borrowed this from the reference implementation in uniorg but it is a bit more verbose than needed and actually confusing since I don't follow the pattern for ElementType in a consistent manner.

TODO

Fix undefined classes

@vidbinadebt

I did something stupid in the rush of dropping the build. When you study the classes you'll find a few classes named undefined littering the codebase. 💩 Clean this up!

TODO

Resolve refused to load font issues

bug
[Report Only] Refused to load the font '<URL>' because it violates the following Content Security Policy directive: "font-src 'self' <URL> <URL>".

registration:1 [Report Only] Refused to load the font 'data:font/woff2;base64,d09GMgABAAAAAlzYAAoAAAAFpdwAAlyNAwEFAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgCJAQgBmADqzgAgZBwypTaDMurPAWHcAcgpe3SklIgwPQAAFDdzsOIFM0eniJ6Vnt7AFRVVVXVlISAx2zbAaCqgh/95Ge/+NVvfveHP/3lb//4l3/7j//6n//7T4HBuPsHwrRsx+X2eH1+w3+49u+5s7sP6KfEKbBQ5SkRSlRTMPq7Gh+hKmyNItVYrFYSMYflpjoiqq8zlVfcXjmYZSNiKtCBjbBuYJJ2fizDlZ2I9+hMVF7Ud50o8CRhegrJkXm4vSSFrgRHEas4TNYk06I4dIPdJO3NFPAPhC/yu5QgIpy/n929CyKWNjSIiT3ErcBXVwKQzX8voe/bRBxmKgItTDSZGcEIRzkXqmYWlpc6gkSLFdhiryZ67YDD9yFHvsMeAhjTy+5g16iE/ZPAf4w/+M6teR8AF6ZrWuh4...ccGw3QNzgGbPbffH6oj3X+P9TPeF/+QwMc9/2lBz8/NESrb+1Dw1T6vj40zmP/54cmMH0/H5ol11/d5Rzjfflr9VHO3mzQnpVtuc6slRvtutbAa3xvs+DUy872nlld29vaWFvfksLjnNfZNtyXbbNm1ovX6uPkpu3rzNrqAtdPYkzDfq32pD7Wn/BzM03tvQBV/Yyb5WVcaPqRueckSqFZlBfznNwmVt5sIx+kpyFKqulLt56Ja6qXYKPUfUuiarfjouEaxRM7ZsSwb1gCSg+LsI1wTYZNefQblC6O1pi6N9hnFHDL+dYq7LDNHoZV1thjiw3WWGcLofBc2de/1f6zH2hYw7BO8TVaHulvv7q7VrdKiERSAvvUqN3C/U71ROrPGhma7zPhq0r07tPVV7cISxh8gZLyQYbj+TU2CwWaFOdLsJTolmQbbP2GpUGegNBDCfOrdKmDXuhSJ0Nw76juEcLNHE4JqcDmFkJEt9bMDo6IsdVKwj8MAwAAAA==' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/ttf;base64,AAEAAAAKAIAAAwAgT1MvMmFLYkoAAAEoAAAAYGNtYXBVZFh1AAAXQAAASG5nbHlmD0UmvgAAdWwABS0MaGVhZCKn9FQAAACsAAAANmhoZWEEQgetAAAA5AAAACRobXR46UsPVgAAAYgAABW4bG9jYQ3zkrwAAF+wAAAVvG1heHAFhQF8AAABCAAAACBuYW1lLsmVwwAFongAAAPtcG9zdK7JwzUABaZoAABM0gABAAADAQUAFxrMGF8PPPUACwIAAAAAAN8EV2sAAAAA3wRXawAA/8ACgAHAAAAACAACAAEAAAAAAAEAAAHA/8AAAAKA/////gKAAAEAAAAAAAAAAAAAAAAAAAVuAAEAAAVuAXoAFQAAAAAAAQAAAAEAAQAAAAAAAAAAAAAABAICA4QABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAIACQMAAAAAAAAAAAABEAAAAAAAAAAAAAAAQVdTTQCAACH//wHA/8...Jvdy11cBJ0cmFzaC1jYW4tYXJyb3ctdXAKdXNlci1udXJzZQt3YXZlLXNxdWFyZQ1wZXJzb24tYmlraW5nCmJvcmRlci1hbGwLYm9yZGVyLW5vbmUPYm9yZGVyLXRvcC1sZWZ0DnBlcnNvbi1kaWdnaW5nA2ZhbgVpY29ucwpwaG9uZS1mbGlwEXNxdWFyZS1waG9uZS1mbGlwCnBob3RvLWZpbG0KdGV4dC1zbGFzaA5hcnJvdy1kb3duLXotYQxhcnJvdy11cC16LWEVYXJyb3ctZG93bi1zaG9ydC13aWRlE2Fycm93LXVwLXNob3J0LXdpZGUOYXJyb3ctZG93bi05LTEMYXJyb3ctdXAtOS0xC3NwZWxsLWNoZWNrCXZvaWNlbWFpbApoYXQtY293Ym95D2hhdC1jb3dib3ktc2lkZQ5jb21wdXRlci1tb3VzZQVyYWRpbwxyZWNvcmQtdmlueWwNd2Fsa2llLXRhbGtpZQdjYXJhdmFuAAA=' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff2;base64,d09GMgABAAAAAZxAAAoAAAACr6QAAZv2AwEDAAAAAAAAAAAAAAAAAAAAAAAAAAAAATgCJAQgBmADj1AAjUjKiqgcy49UBYggByCl0VdRZwCC8wAAsFY/D6pI10ntHgBV1ToxuKkaEH765bc//vrnv78KjN0NsY7r+Yb/+v3Kc/v/mXkLxCqK8IVZrktFRsgOlB+1sexTUatSXdGkSBFIQJVvYY62iPrjo34/xN17JkBnNmmK+2Hb29BVEual5rB6NfWjuHjCr6j/PKrq3/MAvIeHSZAAHofEBRKQLMkiCRKwpdiSVxo3duIkdrN/nHSM6UZd6drpWOpYW+kfa6n9c3WsT/08+dX295yb61YKL+R6r6o7v1zd093TPXk3z86mDJuAXUKWOMQkYARZATMIigEUdVRUzJgwpDWF7zd+Mfwe/3l+lfp/194H6AJXVRd0V03XbRio4hlpQJJBsi2DjJJsJwoYIQ44MCHAD3GI...WKpXqyu/VPu9pQNt/vass0ndrVkfWmZVcnUmberu5MMC9vdw+6tjJLXejtgl1B4loCm7ML40JYTuzKoLqjuRDXvI+Smel0xYW+8MPjfqrkWlbXArsrKI5NbItLvI1ctKO5ENt6yYU2CbwthGXrnWtuqvvUT4/w2iBO6i60+dyMVCabzWcb8tPtuMnNzskeoZk2l8qmsuMXuWhPXK/WvB1XGm8XPLbUhX5Gk1uDP3kL5l+92jw9ednyQgUsxRHisSxgFwEJjhYCLDksC4kHolpcJsEOMYTiVXbQTIGYGh5PRMJM0qQDib1hiKewLJeitFS3mtqSk7sIKDL2H9eCG2qj+1oiHNHSnaU+ZzLEkhBMxU/Sz+JxOJppoo7vxrhatmH2WgJiEupLL5onxwxSZMiSJU+WBvJMJwdpgUtevHNJeua6XIrs/7vxLNqW5B5i6lT30leeZRwlxmOXq96bYxsW5z7/UpP3/wI/45xbPueR6578medYLr7zC/8fAwM=' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/ttf;base64,AAEAAAAKAIAAAwAgT1MvMl9ZV1UAAAEoAAAAYGNtYXBup5HrAAAJWAAABsZnbHlm3yn0iQAAF/QAApQcaGVhZCFecRoAAACsAAAANmhoZWEERAQmAAAA5AAAACRobXR4swkIbQAAAYgAAAfQbG9jYQIufOwAABAgAAAH1G1heHACHQQ6AAABCAAAACBuYW1la7WliwACrBAAAAQdcG9zdKecxYsAArAwAAAWKQABAAADAQMAaqfFLV8PPPUACwIAAAAAAN5fls4AAAAA3l+WzgAA/8ACgAHAAAAACAACAAEAAAAAAAEAAAHA/8AAAAKA////8QKCAAEAAAAAAAAAAAAAAAAAAAH0AAEAAAH0BDgAJwAAAAAAAQAAAAEAAQAAAAAAAAAAAAAABAHkAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAIABQMAAAAAAAAAAAABEAAAAAAAAAAAAAAAQVdTTQDAACP46AHA/8...Vha3MLcmVhY3RldXJvcGUKYXJ0c3RhdGlvbglhdGxhc3NpYW4TY2FuYWRpYW4tbWFwbGUtbGVhZgZjZW50b3MKY29uZmx1ZW5jZQNkaGwIZGlhc3BvcmEFZmVkZXgGZmVkb3JhBWZpZ21hCGludGVyY29tCGludmlzaW9uBGppcmEIbWVuZGVsZXkMcmFzcGJlcnJ5LXBpBnJlZGhhdAZza2V0Y2gKc291cmNldHJlZQRzdXNlBnVidW50dQN1cHMEdXNwcwR5YXJuBmFpcmJuYgpiYXR0bGUtbmV0CWJvb3RzdHJhcAZidWZmZXIKY2hyb21lY2FzdAhldmVybm90ZQdpdGNoLWlvCnNhbGVzZm9yY2UMc3BlYWtlci1kZWNrB3N5bWZvbnkEd2F6ZQZ5YW1tZXIHZ2l0LWFsdAlzdGFja3BhdGgNY290dG9uLWJ1cmVhdQtidXktbi1sYXJnZQNtZGIFb3JjaWQFc3dpZnQHdW1icmFjbwAAAA==' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff2;base64,d09GMgABAAAAAYI0AA0AAAAEnsgAAYHWAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGogMG4SmRhyBqkoGYACBywoKiKAchus5C89UAAE2AiQDz04EIAWMcgeByS1bpRu01kps292SXFogOJmeCkL8ShEEBfHTOaQSbbEAbk63++9nEZWMuT9eCEFEIdDqGKIDEwlKp3X+WVeoc3+EKZXOW9RKhDzS7P////////////////9vJPnPo5t/7n3JeSMvIWEFCQGKgigIMrRW7Vj6RwtqJKyj8CFkMS86yFCWVZfwKNFDHw4xoDMY9rMsq0ewF1kBJ6IbXPTHiPDNJHMeLu8UWZYVCGinmAgHpxHUCKpDfabO23lFfBhl6WsWl1dLjGJbVahQXZZipVC/pkomVRTrjsLCssMFHW8Su6U51c1wq7gBMunv/E4jqOztyikWpVUs5uO2Iuw9DvpxW4oV6lPdsOFF/6zeVebWvFXH...UrqrnKoBXkBXMXdc3mVq4hiWD2IcREtVHHZTBlVN4g9F6155z2YjxoorGINHqG+wQcbBCiNqgNorwhwYNWhUljiCfWtMjZqeZm0koEC7CVhdlVvo53gRS2YJzg2hQKlyNZQXTrKh/emUj31d0xq1VP6c+wBxBhQhkX0lPa2HEXiwnpKW1srooIE8q4kJ7SxuZqhAllXEhPaWNzdYAIc6Uzs6/jItlTxoUydtwpOg0XMm3nTs+4Pe7CqTZAhAllXEhPaWNzHYAIE8q4kJ7Sxua6ABEmlHEhPaWNzfUAIkyoNnbctTm53lPa2HHXOWLKpco8yubaAI/5X7hyrXG5PYyVcjetHXciwF6msSsmuG+IVs7j/RGIZKsAESaUCekpbVYNkZmyC8B4yszpufE8OFGu3sbmGgARJpTxEV++95w7n+X0eyXt+5YAIkwo40J6SoOnOQOK1+fuRd51q0q8Ah6BoTUqsC6YJ+RyZT+Xw+LAzdIylzkud3zedO49DAAA' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff;base64,d09GRgABAAAAAgrUAA0AAAAElPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAGSRAAAApIAAAQMLxsv50dQT1MAAZTYAABOhQABE0aIvxr7R1NVQgAB42AAACd0AABVSptVOxRPUy8yAAABoAAAAFcAAABgKreuYmNtYXAAAA9sAAAubAAAZYo1eewlZ2x5ZgAATwQAARrNAAIG2WorKltoZWFkAAABMAAAADQAAAA2LWDLTmhoZWEAAAFkAAAAIAAAACQe9RnAaG10eAAAAfgAAA1yAAAnzgHTThRsb2NhAAA92AAAESkAACfUCRk8iG1heHAAAAGEAAAAHAAAACAKCwDkbmFtZQABadQAAAKHAAAF4qga4kpwb3N0AAFsXAAAJeUAAGSt3GSztnjaY2BkYGBgZrl74inDrnh+m68M0twMIHDn065PEHo3+/cHf2pksnhAXDYGJpAOALPYDwZ42mNgZGDgWvE3g...ajkDJ0Jy7m9fYARuhAd8H1vMp64lFeZT/BskRhohC/TbRIXIJ1iV6JFHYkZibuxgeJhxKL8YfEksTT+CTxXOI5/D3xduJtnEp8nPgY3/HTBYcUEp8mPlPK/USutIlMpBKck4bKBO8Eu5UN64b5KgxLw1KVDMeG41SO+31R5bnfDlWl8LFwharsfi9U1cP3w32qRtQsaq5qRa2iVqqu+61O5UczozvVOdHsaLaqH22JnlcN3G9sqiD6KjqiGp1+Pf6fzB8I9l/JW4U1X88UBW2C66CYq5jGQdPgqgo9Gpg2PG/HSo8aphnPz+xpT06G0lLbuHk78rQWKy35PKuLTpvJBcg7+0hA0OI7xPeE+G5O1z77ygeBZAVDVrD2ev4pZ46Bt4ViFPy7OQGByse9QvTqm9a87sdIJKqbpry+rz7NpySIS9mXTvfr39w1C0DQFVZbXTQsd45haHXW67C/Cv9L12B/XfVX0VZnu4qWv4b+K1dQf1WUK+H/ARWMSxg=' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff2;base64,d09GMgABAAAAAZ6cAA0AAAAEviAAAZ4+AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGogMG4TcKByBqkoGYACBywoKiKkshuRRC89UAAE2AiQDz04EIAWMWgeByS1bBzO00v8f+3kvvCX68AwGeLZpWWtmP8t9dA6pxNFaAJ3T++3LZBGZxLYX8k19QYuO6hjDCxsOJW9Wv24obphO0QvXbQhktsjavD6L7P///////////////29rWUQ6nd3/9177UqVX6UiogUSTAGMZbONKCIljx04gSjOGaKvgQv8j4WM2QYowUVmcSipESV5wsWJLYSooxTSIwDUREk1rErO1uDxTaBmkzahtS1hEHaJyQQwFlQu6mvT6jiQYkFp3hjSkozGdHE1lFraJDfBkMIAlx4ErCgPn9NwordAX12q0yEIvYVYoYGAM1n0YohkxiRZk2drOYa005CTkjREIMUoJESJEi4JqKGghSlijFLRA...vay8QjyHmPXrvooxrlrCsmgybai2SogmeU1gYh1ADJke/kwbtOhcSI2c/sdVhuKtkmbpmxgbXcmN0jvxufbxeOaJMAEieHMgUh68yLOxOarPbEVK0UzazLfABCMIJiOEFSNMNy87uYGEFSNMNyeqkIwQiK4QRJ0QzL6aURjKAYTpAUzbCcXjqAEIzTjDbm5TqhzKcYTtAsN7+z62Y4QWq4uM1nODe9C1/nACIMJ0gGk8XmcHmUOhcQYThBMpgsNofLo9R5gAjDCZLBZLE5XB6lzgeIMJzg8qi5L5VPnW9zuDxq7ks7MYLB4ui9akqdAzi9HwrdLsXSer2GSvGQ4uY+E9Bn5FEVI+z3CJXlVF8KIrpUACEYQTGCpGiGrRIkkdINwHA1GztxcXxwprz0YTm9DAAhGEExfI7TuHd877xzxejfLt1DlwARhhMkg8lic7jTu4eitv3qRd6oNQiJC7g3a4bRZj8br/3lZf6xnOhYuCyVOfdxdO7H0Cv3XgAA' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff;base64,d09GRgABAAAAAi9oAA0AAAAEs/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAGucAAAApIAAAQMLxsv50dQT1MAAbEEAABW7wABLijDHQkvR1NVQgACB/QAACd0AABVSptVOxRPUy8yAAABoAAAAFUAAABgK+OxuGNtYXAAABLYAAAubAAAZYo1eewlZ2x5ZgAAUmwAATOXAAILDJHyiHloZWFkAAABMAAAADQAAAA2LDXMIWhoZWEAAAFkAAAAIAAAACQdyRlbaG10eAAAAfgAABDfAAAnzjw8I4Zsb2NhAABBRAAAESUAACfUCSJfmG1heHAAAAGEAAAAHAAAACAKCwDubmFtZQABhgQAAAKBAAAF1qWJ4Alwb3N0AAGIiAAAJeUAAGSt3IG0A3jaY2BkYGBgZrk77YvK1nh+m68M0twMIHDn025bKB3wbcufGpksHnugWjYGJpAOAKUIDqp42mNgZGDgWvE3g...iGo5AydCcu5vX2AEboQHfB9bzKeuJRXmU/wbJEYaIQv020SFyCdYleiRR2JGYm7sYHiYcSi/GHxJLE0/gk8VziOfw98XbibZxKfJz4GN/x0wWHFBKfJj5Tyv1ErrSJTKQSnJOGygTvBLuVDeuG+SoMS8NSlQzHhuNUjvt9UeW53w5VpfCxcIWq7H4vVNXD98N9qkbULGquakWtolaqrvutTuVHM6M71TnR7Gi2qh9tiZ5XDdxvbKog+io6ohqdfj3+n8wfCPZfyVuFNV/PFAVtguugmKuYxkHT4KoKPRqYNjxvx0qPGqYZz8/saU9OhtJS27h5O/K0Fist+Tyri06byQXIO/tIQNDiO8T3hPhuTtc++8oHgWQFQ1aw9nr+KWeOgbeFYhT8uzkBgcrHvUL06pvWvO7HSCSqm6a8vq8+zackiEvZl07369/cNQtA0BVWW100LHeOYWh11uuwvwr/S9dgf131V9FWZ7uKlr+G/itXUH9VlCvh/wEVjEsY' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff2;base64,d09GMgABAAAAAZ1MAA0AAAAEvUAAAZzvAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGogMG4TcQByBqkoGYACBywoKiKZshuQfC89UAAE2AiQDz04EIAWNJAeByS1bNzO03k/xt/e6st5xlhatijhWZwJB0IDI/MfoXyO+mXoANtXuv5unEZWMuYf5ACEygrTqGMMDGw6lMnvVEVSv/X6Q0JvVx4kf2fTZ////////////////////39fyI/zN3kySzuxuEpKQEEDCRwiIiKKAFX+1rbWfq62tbe+uvYMohBghFk41jBAzqg1OlRiqyiWpslnGJBGaaS4o0NJW2W4QRzpMorRLCmVFfNvrIaloRvoVNBkEaMg2Rp39RMZoIEuhdlJPMWNUPYv4duDmhwta2WyvOcx7R3NWxP8l23CcQLihHksq6UlLXORWYok9tWe5I25tlhuHZp4xWaZtIR2Mo60NTQajJ6JQyLl2TSK2...H21VqNZ2hKHm60hmqsxj6dWNReJh5B1l28puijGuWsKyaDCs0hGargGaUNgxBqgGThWz146lRIjKi+sddh2VWyTdxScQBrOZndhd/J55vCEW0SQOLkUKYgZJ158ciEJqs9Ma3W6+JKm3vZBxBhQhkXUmlj3XzbxIRU2liXV0WECWVcSKWNdXk1woQyLqTSxrq8OkCEuTbZNa/rItmnjAtt3Xxv1224kBm3bvuMu/E2b3eAxLiQytI+23FNXhdIjAupLO2zHdfk9YDEuJDK0j7bcU1eH5AYF45r5tuTN6/vsx3XzLefkwml7dyzTV4HOO5/8No11rNCb6yhpXjIcPVtBIwzcpkWIxzvEmqWpV4LIrpUACEYQTGCpGiGbSVIImU0AMPVbOzExfJgo7z0YTm9DAAhGEExvMZa95b7ti876n3buv2NABGGEyTFovnYnHJvUFTfr17kHbUuxAO4N8fMEr2y32q8q798MP9YDs3KwzIyz330y30Z+o77dQEA' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff;base64,d09GRgABAAAAAi5UAA0AAAAEswAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHREVGAAGtTAAAApIAAAQMLxsv50dQT1MAAa/gAABW/gABLkBwQqjBR1NVQgACBuAAACd0AABVSptVOxRPUy8yAAABoAAAAFYAAABgK3+woGNtYXAAABLQAAAubAAAZYo1eewlZ2x5ZgAAUmAAATJmAAIJv6Y1plxoZWFkAAABMAAAADQAAAA2LMjMCWhoZWEAAAFkAAAAIAAAACQeXRl9aG10eAAAAfgAABDVAAAnzihtiS1sb2NhAABBPAAAESQAACfUCSECn21heHAAAAGEAAAAHAAAACAKCwDlbmFtZQABhMgAAAKaAAAGDq236pRwb3N0AAGHZAAAJeUAAGSt3Hez6XjaY2BkYGBgZrmr+aXHJp7f5iuDNDcDCNz5tNsGSvt/9/hTI5PFownksjEwgXQAAIa8Dah42mNgZGDgWvE3g...iGo5AydCcu5vX2AEboQHfB9bzKeuJRXmU/wbJEYaIQv020SFyCdYleiRR2JGYm7sYHiYcSi/GHxJLE0/gk8VziOfw98XbibZxKfJz4GN/x0wWHFBKfJj5Tyv1ErrSJTKQSnJOGygTvBLuVDeuG+SoMS8NSlQzHhuNUjvt9UeW53w5VpfCxcIWq7H4vVNXD98N9qkbULGquakWtolaqrvutTuVHM6M71TnR7Gi2qh9tiZ5XDdxvbKog+io6ohqdfj3+n8wfCPZfyVuFNV/PFAVtguugmKuYxkHT4KoKPRqYNjxvx0qPGqYZz8/saU9OhtJS27h5O/K0Fist+Tyri06byQXIO/tIQNDiO8T3hPhuTtc++8oHgWQFQ1aw9nr+KWeOgbeFYhT8uzkBgcrHvUL06pvWvO7HSCSqm6a8vq8+zackiEvZl07369/cNQtA0BVWW100LHeOYWh11uuwvwr/S9dgf131V9FWZ7uKlr+G/itXUH9VlCvh/wEVjEsY' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff2;base64,d09GMgABAAAAAQ9AABEAAAADHJgAAQ7aAAI99AAAAAAAAAAAAAAAAAAAAAAAAAAAGoNsG7l0HIG3FgZgAPR8CIEoCZwMEQgKh+94hu1bATYCJAOqPAuVIAAEIAWJZgfyWgyBVlu0z5KoNW6bfpX07oBDtyGA9WZq1fS/hyuRDtl92jGxKDaP1rmIQJ59/RqL3e4TAd0GCKhS0frTS/b///////+25IvsZ0mgL0lb/o6pIDJxnLrtfgyCgozAPEajhFzBa2/aOucu9XnIlFLVHDyyGNv2rdI0vo+UYqTjaWTn42QUR0o0yhEiZECcIap8WTALSteOrRTtQ53H20wHXlvl251DHPibXPHLqceCluwMFHyHZuXWeyd96iA5NnGR2pW31EC8wsEggIODBqiClHYoAeBZdTACaDS/RaWJzAFaOzrmCKFXUraT9b6tNfvVxzrdZ+4bjcUe9GQvQq4I7G4BurHUU/elVVTyMYuA...qkZ1z3mcLaeoTE364XEhvyLpcyHJEyZcr76wo25UfrlpeM7Avp+h7UhqQXUjtNgK6ybGsVilGsYyazkDrP1FLWRm7gaeEJfQNijGQFw57iGi4g8WIW89ganSFjLn6Hb1qD30wlLOX6zjwn/WbMYb/wSlgg/0jLZEx+h2aek9+eJWzJ/vbLSMhlhmX8D8SSIAO/F0j+qzAsiaZ8NeSCZ/P//Hjs+BBfRmE0FIeUd5RGqUfBm3LGReXIWBgbMW6l8uBMmklnqUSPYi0ADhqFEEDoX/Mgod++9csssmUQ/4DzJwnaEWo4sw1RAaKIRW5ohzbevwEc2MmAguTQ/RzADMv8M8cW3BbaFUo+Ok+UguRetirPLf1xan/v/9RuqXRTvLXRrbInWoEfo5A4sH8xtuif0ALgkB+NUf2JgjbPeoGIekpmLZfocJkFh5yp22563esKvQoYWdOcFiOFP8/akxmhQDmVzcrsEqVk/geS/faGtOnHuMr+mUovQ+khAAA=' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".

registration:1 [Report Only] Refused to load the font 'data:font/woff2;base64,d09GMgABAAAAARYMABEAAAADNLgAARWlAAI99AAAAAAAAAAAAAAAAAAAAAAAAAAAGoNsG7pOHIG3FgZgAPR8CIEoCZwMEQgKiIo0h4Y9ATYCJAOqPAuqQAAEIAWJTgfyWgyBVltY3LIGqsXYjK2qvWpyhESQEET+OZ62TSCvJL+7TK+gNYZJj7eKm9g1ogdsSVfuZt5+gG1L+Wa3A/zxue9msv///////////39j8iPW9jNv4c0erICo4Jla4lHWN+0LTbz4EH2QlLyk6FqxuOwwqVEjrZrqrnSzBlVsOwILVDbvJAQJcwtSmQoU700WdfA6VhTvgdF6G3zslrJac22OGy9bwCXcUb+pxd51PZea04McQ0tZKuIjPYHN4jv6SIaCmeN8Qu68nLykChxsyEGP0kujGx/T+aJm5rTAA7rim1qqt8Zvkiy0d/7kF6TzPcv3VX2F9f7n320lCZKQhFYAXU7qKpdBdRe3b5wK...OS+W95/JTc9ghd/kthfxPhrAbS/t26aRD+B8P+BkaQAobbSGx4jGvSHEoTjsZjUNd8pvCXUjSXjeKa8Kw0RNRkkS+l2Cd0iGliyE791jyASBTVqZzKFP4hkcjIaQzXEeOYW/ERPkUGQ6Y81Bzv6OD5RuERA7w8RHIvLcL0w9Do4IeeeajYoV9k4URG0PA9xPymoYYL+J0SMm+s+eM4EbxWPPPp8RTHqB59E5oB/5JIm9SkHfrFg7deRN80zIW5McO/Sd7n0lw6TtvM6+ksYQ8apQIQqmbaHAipWctqFQ6ropHwJ758ufUSgQ+eG+ifiqPOu0tQR90NzL7lp4D6afYzS08Ki8A3QjWCVCfwGGtcs42JFUIlL/8ZXx/1sNuHvb44ftm/LEYocCDUqxsRH0Goex8EMO97IPU/kWsiMjL1aD4f0v+WBpCzMO+V6VLwXPeOJkEkS3rmOVpK764j9FdsZZ1KYSUzTxDA3EvsrTXy/ieOZf+i+FaAmAcAAAA=' because it violates the following Content Security Policy directive: "font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net".
TODO

Align home-page and reader logic

@vidbina

Right now, the home-page has been the thing we focused on, but we basically want the same behavior that we have on the home page on reader pages.

Handle SSR on the reader pages on par with the home-page and handle indexing on the reader pages on par with the home-page.

WIP

[50%] Simplify file source access flow

UX
DONE
Add a clear Follow URL CTA
@siarhei
- State "DONE"       from "TODO"       [2022-10-06 Thu 08:01] \\
  Siarhei provided updated sketches at https://www.figma.com/file/DenroEWfValwUxKZJdtLW7/formation.tools-(Copy)?node-id=343%3A598&viewport=-1853%2C254%2C0.14

Remove emphasis from Visit Source button and add a clear Follow URL CTA (Call-to-Action).

Problem

As a user, I press the Visit Source button expecting to be lead to the URL entered inside of the URL input box. This is a usability problem. We need a strong CTA near the URL input box that does exactly what a typical end-user would expect: lead one to the page that matches the entered URL.

💡 Try to enter https://gitlab.com/formation.tools/eng/proto-01/-/raw/hack/README.org into the URL input control to see what we mean. When pressing the blue button it only navigates to the source of the current page. The lack of a connection between that prominent button and the input text is a bit confusing. Following the entered text is only possibly by pressing Enter.

Definitions
Background

comments

💡 The URL input textbox will very likely disappear once we allow people to login with their own GitHub and GitLab accounts. At that point, users will just navigate to the files they want through the sidebar menu. Since we're not there yet, the URL input box is an interim solution for now so it doesn't have to be perfect but should be at least "usable enough" -- as in, not confusing even the people who made it. We improvised input bar without the guidance from design so this explains the poor UX. Now we're trying to improve since we're hitting a point where the previous solution is no longer good enough.

Users can currently press enter to continue upon entering some text into the URL text input. This isn't always very intuitive since there is a big blue button begging to be clicked right next to it. 😅 This button doesn't quite do what one is expecting, so we want there to be a button for the folks who wouldn't intuitively go for the enter key that does exactly what 80%+ would expect from such a a button without reading its label.

Suggestions

I'm thinking that a good starting point would be to move the Visit Source button to an icon-only source button. Perhaps we can add it as an option to the perspective-selection button groun (where we can switch between Prose and Kanban views). But we're also open to a different design since I would understand if you argue it doesn't belong there since Kanban and Prose are both in-app perspectives and this Visit Source action would lead one out of the app and perhaps deserved a different level of emphasis for that reason.

For reference, you can see how GitHub approached a similar problem on page https://github.com/rasendubi/uniorg/blob/master/README.md?plain=1 in the bar with the Raw and Blame buttons.

This bar has Display the source blob and Display the rendered blob buttons as well. The Raw button does what we previously did with the Visit Source button: it leads one to a different place on the internet that serves as the source of content. The Display the source blob button just displays the source of the file in-app (never leaving the main app).

I'm not sure on whether we eventually 1) lead people out of our app to the source or if we 2) offer them a source-only representation in-app, but since we already handled option 1 with the Visit Source button, we can just model the behavior of GitHub's Raw button which does more or less the same thing. This approach keeps the implementation step easier as we already have the Visit Source bit implemented and would simply need to restyle it. Rendering the source in-app, however; may require us to design another perspective for that behavior that we should schedule as a follow-up task and complete at a later point in time.

TODO
Design source perspective
@siarhei

In Add a clear Follow URL CTA, we touched upon eventually providing an in-app source-only view which would allow folks to see and copy the source code conveniently.

As a user, I want to be able to quickly copy the source code for a given page.

Background

We currently enable this by allowing users to follow a link to the Raw representation (the exact version of the file that we read for parsing but this is technical detail so just ignore this). Going to the raw page, leads a user out of the app and the user has to copy the content by selecting it all (which is easy enough with keybindings) and copying it (also easy enough with keybindings).

Goal

We want there to be a perspective where the end-user can:

TODO

[0%] Handle basic invalid target cases more gracefully

UX

In the spirit of keeping things simple and not trusting any input, the user should expect some basic checks to prevent them from doing things that must not work.

TODO
Fix timeout error when loading large files
bugfix
:ID:       8f0aaa91-7845-4dee-bb3e-7f256d7d13fe

Loading of files such as https://raw.githubusercontent.com/sachac/emacs-news/master/index.org currently times out with status 413 and the following logging output. 😰

[GET] /r/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3NhY2hhYy9lbWFjcy1uZXdzL21hc3Rlci9pbmRleC5vcmc
18:53:40:72
Function Status: None
Edge Status: 500
Duration: 29697.85 ms
Init Duration: N/A
Memory Used: 741 MB
ID: fra1:fra1::4v64n-1663095220604-c6e5ca4e426f
User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36

url aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3NhY2hhYy9lbWFjcy1uZXdzL21hc3Rlci9pbmRleC5vcmc
2022-09-13T18:54:05.666Z	f70e20ab-d399-4148-8d00-5a652bd01208	WARN	Warning: data for page "/r/[url]" is 7.16 MB which exceeds the threshold of 128 kB, this amount of data can reduce performance.
See more info here: https://nextjs.org/docs/messages/large-page-data
[ERROR] [1663095250473] LAMBDA_RUNTIME Failed to post handler success response. Http response code: 413.

This problem may be solveable by incrementally parsing larger pages and gradually streaming chunks of parsed content back to the client but I'm not sure how easy it would be to make this happen.

TODO
Check URL before routing
UX@tijan

Avoid people from shooting themselves in the foot by implementing basic heuristics to check that GitHub and GitLab links are raw links:

In case the links are not raw, present an alert for now with the error. We'll show something nicer in the future when we have time.

TODO
Check that retrieved data is valid Org data
UX@vidbina

Right now we run HTML input through the Org parser if the URL was invalid and pointing towards a regular webpage. We should at the very least check if we can discern plaintext input from HTML input by checking the mimetypes in the response.

DONE

Retrieve all top-level tasks

@vidbina
- State "DONE"       from "TODO"       [2022-09-04 Sun 16:22] \\
  Implemented and merged to mainline

In order to populate the Kanban view (where the first TODO may not be part of a first-level heading), we want to be able to extract all top-level tasks from a document.

For the following snippet snippet we can list 3 top-level tasks, being:

* Background
* Tasks
** TODO Think about what to do
** Something in the future, not sure yet
*** DONE Procrastinate
*** TODO Figure out what is in the future
**** TODO Collect underpants
**** TODO ...
**** TODO Profit
* Conclusion

Any of the subtasks should only be visible when navigating into that level by clicking on the parent card.

DONE

[100%] Create tab button group to switch modes

@vidbina
- State "DONE"       from "TODO"       [2022-10-15 Sat 15:37] \\
  This has been solved with a mode selection component, named ModeSwitch

For user to switch between the different modes/perspectives/views, let's just call it perspective, of a document we need something better than the toggle so let's define a button group that looks a bit like the Preview/Code tablist on pages such like https://tailwindui.com/components/application-ui/navigation/tabs to make it much clearer which view is currently active.


comments

I guess perspective is clear enough as it provides a perspective on a document. Modes may introduce confusion if we were to support vim-style modal navigating/editing at some point and views already has a meaning with regards to interface development that could confuse us, as a team, or readers. Perspective seems like a word that isn't used too often within the realm of text-editing and interface development to allow for easy misunderstanding -- I hope 😅.

DONE

Spar with design-team on placement of such a control

- State "DONE"       from "TODO"       [2022-09-25 Sun 22:12] \\
  Top bar is the place for now, but we will revisit this at a later point to localize the perspective-switch in the perspective view itself.

Reach out to @siarhei and team to figure out where to best place the perspective control.

DONE

Update toggle-references in zero section

- State "DONE"       from "TODO"       [2022-09-25 Sun 22:13] \\
  Not very clear. We need to implement images to clarify this even more.

The opening section of this document points people towards the Toggle to switch views. Once's we've been able to rip that out, we can update the text to point viewers towards the new controls.

- State "DONE"       from "TODO"       [2022-08-31 Wed 15:51] \\
  Merged into mainline a few days ago
DONE

Implement Tag component

@tijan@assutech
- State "DONE"       from "TODO"       [2022-08-31 Wed 15:51] \\
  Merged into mainline along with the Link component
DONE

Resolve GPL licensing issue

- State "DONE"       from "TODO"       [2022-09-07 Wed 21:53] \\
  It's GPL3 now. It's a prototype build so we'll have to get over it. The idea of keeping this GPL3 is a fun challenge as well.

At the moment, the front-end will have to be released under GPL3 as far as we understand. This represents a risk for the commercial interests of the project and thus it is important to consider how we design the system going forward. Some approaches would be to:

TODO

Look into non-GPL3 parser availability

The uniorg is licensed under GPL3 and possible must be because it represents a translation (see GPL3 text for the definition of a translated program) of the org-element.el implementation in Emacs also under a GPL license.

The alternative org-parser is also licensed as GPL3 so, apart from the effort to integrate, this would not be a valid option either.

DONE

License front-end under GPL3

- State "DONE"       from "TODO"       [2023-02-05 Sun 17:00] \\
  Already licensed under GPL3 so this topic is covered.

If we cannot find a permissive parser, we will have to license the front-end project under GPL3.

DONE

Research how to deliver back-end logic as separate modules/services in Vercel

- State "DONE"       from "TODO"       [2023-02-05 Sun 17:08] \\
  We already know how to tackle this issue so let's just mention the solution.

In order to avoid having to bundle everything into a GPL3 app, we can provide all base front-end logic in the app and then take the marketplace approach and offer integrations with services (our own or third-party).

We can ship back-end logic into a separate app and then use the NextJS Rewrites facility to points to the necessary endpoints, wherever they are.

Research

TODO

[%] Study task dependencies

TODO
Read UOMF: Advanced Usage of Dependencies Between Tasks Using Org Mode by Karl Voit

[33%] API v1

TODO

Define Documents endpoint

All data is contained in files which we'll call Documents. These Documents are currently retrieved directly from a third-party HTTP server that serves us the raw plaintext, but we want to hit our internal documents endpoint instead that will provide us optimized content to work with.

Problems with the current design:

We eventually don't want to show the content for every raw/plaintext page on the web but only for the pages that we have some write-access to git repos.

We will therefore need a data pipeline that can ingest data from repos (on a schedule and triggered by hooks), and populate our internal docs structure such that we can provide fast retrieval.

TODO

Define Bookmarks endpoint

DONE

Define Bookmarks structure

- State "DONE"       from "TODO"       [2022-11-12 Sat 15:32] \\
  Stub basic properties of inbox

An inbox entry needs to have the following properties:

[0%] Browser Extension

As a knowledge worker, I want to be able to quickly record web pages/resources and catalog them for future reference within a single interaction.

TODO

Explore how to solve SSO for an extension

Can we allow a user to SSO-login through a regular tab and then use that session data for the extension? AFAIK there is some scoping between tabs and extension and we don't want to complicate the sign-in experience in the extension.

Ideally, we can facilitate SSO from a (Google, GitHub) session that is already live within the browser.

TODO

Stub extension UI

[0%] VSCode Extension

TODO

Scope what we want to do with a VSCode extension

@vidbina

[0%] Mobile

CANCELLED

[25%] [1/4] Project Alex

rogue
:COOKIE_DATA: todo recursive
- State "CANCELLED"  from "IN_SCOPING" [2023-01-06 Fri 14:47] \\
  This was a gimmicky thing that popped up in conversations between David and Alex. No headspace to focus on play with this since we have to clarify focus on the story and ship v0.1.0 so I'm dropping this from the board.
DONE

Ideate on what the hell this really means

- State "DONE"       from "TODO"       [2022-12-09 Fri 10:14] \\
  Done on-stream
TODO

[0%] [0/2] Stub NextJs project

TODO

Stub project

TODO

Host on Vercel

Background

👋🏿 This is an Org file, that markup format associated to Org-mode the so-called killer feature of Emacs 🐃🙊 but that's not the point. I've hated Confluence, Notion and consorts 😠 with a passion for a while and was keen to have a way to collaborate through plaintext with folks. It's obviously unfair to ask folks to learn Emacs, so I figured building a tool that allows folks to read Org files is at least something I can do to stop my whining about Confluence, Notion, et. al in the "shut up, fix it" spirit. This is the scrappiest prototype that I could whip up to start flirting with the idea. 🌱

The cool thing is that such Org files can be presented differently to provide a better overview to you, the reader. We can look at them as prose, as a kanban board (which displays the entries in this document that are tasks), as an calendar (for a view of everything that has dates/times associated to them) and more.

The toggle top-right can be flipped to switch between prose and Kanban view on this doc. Yeah, it's a horrible UX but it was the quick-and-dirty thing that we could built in there. 🙈

🥱 TL;DR

The "big idea" 💡 here is that most of this is kept as plaintext and that a git repo is the conduit to keep track of your content and changes. For most users, this is not interesting so we can provide them a web tool that abstrats all this git and Org stuff away from them but will allow the other weirdo hackers like myself to just live in their editor of choice and not worry about context-switching between their editor and slow web-tools.

Many of us probably agree that git is a great way to collaborate and track versions of ever-changing text. We don't need our data stored somewhere in someone else's database and request permissions through clunky APIs to access it when you can just have it on a repo on your machine. We want to offer a an easy API and good utils to just do whetever the heck you want with the files on your box. Honestly, with the development in tooling recently, decent search or other capabilities should be easily serviceable by your own machine through different utils (some perhaps built in Rust). Our computers are definitely packing enough heat to handle all the compute needed to for a local knowledge base.

Depending on how poorly (or warmly) this is received, I will decide how to move forward, so that feedback is needed for me to know if this is a moderately sensible idea or totally ludicrous. 😅 We're thinking about supporting collaborative editing in the future. I'm already setting up a coffee meet with the author of ProseMirror to explore this. Imagine being able to look at a prose, kanban or calendar diffs on the state of an Org-file when you come back from vacay 🏖️ to get a quick sense of all the things that have changed. This is also on the wishlist.

So in the spirit of scrappy prototypes, the repo is online and GPL3 (because I'm using @rasendubi's uniorg)... Roast away! 🔥

WIP

Stack

Infrastructure

digraph G {
  compound=true;
  //bgcolor="transparent"

  <<infra-domains>>

  <<infra-vercel>>

  <<infra-plausible>>

  <<infra-associations>>
}

file:gen/infra.overview.png


comments

🧭️ Everything that is dotted and in red is on the way out! Things that are gray and dashed are ideas to likely be introduced Everything green and filled is live at the moment and everything else is just there but not highlighed to keep the diagram from being too cluttered.

file:gen/infra.overview.png

Vercel

We use Vercel as our compute provider because it is easy.

subgraph cluster_scope_vercel {
  label = "Vercel scope"

  <<infra-vercel-apps>>
}

Prototype Application

The prototype app is our current drop-in point -- the one place where you end up for everything. Since we're in an early testing/validation stage, we are keeping this scrappy for now until we know what to really build.

node_vercel_proto [shape=box,label="proto-01",style=filled,color=lightgreen];

APIs

We anticipate needing different APIs at a later stage for different functionality, e.g.:

All these APIs and integrations can be separate Vercel apps just to keep things more cleanly isolated. That way we can decouple deployments of our different services.

Concepts
💡 This is just a concept section of APIs that we can implement at some point. As this section is commented, the dot diagram code below is not rendered into the infra overview at the top of this section.
node_api_v1 [shape=box,style=dashed,color=lightgrey,label="API v1"];
node_api_v1_data_git [shape=box,style=dashed,color=lightgrey,label="API v1 git data svc"];
node_api_v2 [shape=box,style=dashed,color=lightgrey,label="API v2"];

Proxy/Rewrite

We started off by directing all of our domains to a rewrite/proxy service where we resolved paths. This allowed us to gradually build out our stack with different services that we can mount under arbitrary paths on our target domains but was challenging to develop with. On , I had a call with Hassan about DX and we decided to move all rewrites to the prototype project directly.

By using the rewrites facility in next.config.js, we should be able to reference environment variables which can be defined using .env.local files during development (and pointed towards any arbitrary destination) and through the Environment Variables platform facility on a per-branch level in the Vercel platform. This should provide us the needed control and a tenable DX.

subgraph cluster_vercel_conf {
  style=dotted;
  color=red;
  label = "vercel-config";
  node_vercel_conf [shape=box,label="vercel.json"];
}

Some of the rewrites that we conduct are rewrites to external services. The last defined rewrite and therefore our fallback path is the prototype app for now.

node_vercel_conf -> node_api_v1_data_git  [label="/api/v1/data/git",style=dashed,color=lightgrey,ltail=cluster_vercel_conf];
node_vercel_conf -> node_api_v1  [label="/api/v1/*",style=dashed,color=lightgrey,ltail=cluster_vercel_conf];
node_vercel_conf -> node_api_v2  [label="/api/v2/*",style=dashed,color=lightgrey,ltail=cluster_vercel_conf];
node_vercel_conf -> node_vercel_proto  [label="/*",ltail=cluster_vercel_conf];

Eventually, we can use the rewrites/proxy mechanism to mount all of our own services and 3rd-party services under friendlier paths, for example (and bear with me, this is just me musing):

DNS

We have the following domain names:

subgraph cluster_domains {
  label = "Domains"

  node_subdomain_prod [shape=box,label="proto.formation.tools"];
  node_subdomain_hack [shape=box,style=dashed,color=lightgrey,label="hack.formation.tools"];
  node_subdomain_staging [shape=box,style=dotted,color=red,label="staging.formation.tools"];

  node_domain_a [shape=box,label="formation.tools"];
  node_domain_b [shape=box,label="forto.dev"];
  node_domain_c [shape=box,label="f7n.io"];
}

We use the Rewrite (Proxy) facility from Vercel to manage these domains through a single Vercel project -- a convenient drop-in point to serve as our nice traffic-direction point.

node_subdomain_prod -> node_vercel_proto [label="Production"];
node_subdomain_hack -> node_vercel_proto [style=dashed,color=lightgrey,label="branch: hack",label="branch: hack"];

node_subdomain_staging -> node_vercel_conf [lhead=cluster_vercel_conf,style=dotted,color=red,label="branch: staging"];
node_domain_a -> node_vercel_conf [lhead=cluster_vercel_conf,style=dotted,color=red,];
node_domain_b -> node_vercel_conf [lhead=cluster_vercel_conf,style=dotted,color=red,];
node_domain_c -> node_vercel_conf [lhead=cluster_vercel_conf,style=dotted,color=red,];

Plausible

We use Plausible for analytics. On the Plausible end, only two artifacts are relevant:

subgraph cluster_scope_plausible {
  label = "Plausible"
  node_plausible_v1_api_event [style=dashed,color=lightgrey,shape=box,label="/api/event"];
  node_plausible_v1_script [style=dashed,color=lightgrey,shape=box,label="/js/script.js"];
}

In order to minimize the potential for loosing data due to ad-blockers, we proxy our own paths onwards to Plausible as suggested in the Plausible documentation on dealing with missing data (link captured on ).

node_vercel_proto -> node_plausible_v1_script  [style=dashed,color=lightgrey,label="/js/script.js",ltail=cluster_vercel_conf];
node_vercel_proto -> node_plausible_v1_api_event  [style=dashed,color=lightgrey,label="/api/v1/event",ltail=cluster_vercel_conf];
DONE

Stub Vercel project that provides a rough outline of this infrastructure

- State "DONE"       from "TODO"       [2022-09-14 Wed 11:19] \\
  Resolved with the help of Sebastian from Vercel. Core point was that we only defined a non-root rewrite =/:match*= instead of defining a root rewrite =/=.

Stubbed vercel-config but it is broken. We debugged this together to no avail and I just filed Case #00097879 with Vercel Customer Support.

TODO

Proxy Plausible paths

In order to ensure that we hit our analytics back-end, we can define some rewrite rules towards Plausible.

TODO

Parameterize Plausible magic strings

@vidbina

The Plausible config is hard-coded in the codebase and pollutes our analytics because it also records localhost or staging traffic.

TODO

Think about how to solve payments

- State "TODO"       from "TODO"       [2022-09-14 Wed 11:20] \\
  Not actively tackling this since we are too early stage to worry about payments at the moment. We're focusing on the big picture bits for now.

Wants:

Blogposts

Decision

DONE

Develop marketplace concept

product

This is a product concern so I'm signing this over to the product scope which is in the shared intel repo.

Principles

Use these as tools to guide you through every engineering choice.

Minimize Toil

We are a small team and probably always will be (kind of like a small formation of synchronized dancers 🩰 or a well-tuned squad of special forces operatives). Because of our size, we have to build solutions that minimize manual effort on remedial tasks.

Refer to [[https://sre.google/sre-book/eliminating-toil/][Eliminating Toil [Google SRE Handbook]​]].

Design First, Implement After

For anything we attempt to engineer, we make it a habit to design first by drafting a document that outlines the problem, potential solution candidates with reasons for why the candidates are preferred or not. This document is already an example of such a text because we have been "thinking out" ideas in this doc. 😅

💡 Really try to not initiate implementation work without first going through a design effort!


comments

👨🏿‍💻 License to Hack: Sometimes a quick and dirty prototype is arguably part of the "design effort" and maybe even a required step in order to understand a problem and related constraints (for example tooling constraints) better. Somethings are simply hard to sketch out in advance or phrase in clear terms, so, in the spirit of show/hack-and-tell, feel free to whip up the occasional prototype to serve as "documentation" to communicate a design.

When engineering software, start with a README in a repository and document the problem and some solution candidates.

The following is an example of a minimal README for an imaginary project.

#+begin_src org
,#+TITLE: Org API

,* Problem

- Org is a rather extensive (complex) standard
- Changing source on a per-character basis is leaves room for "breaking the format" (e.g.: when necessary punctionation is altered
- From a user-perspective, Org operations happen on an Org-primitives (e.g.: we add text to a heading, we remove a link, we boldface a phrase of text) which a renderer or editor will need to understand

,* Solution Options

- find Org parser that is usable with JavaScript (because we're building something for the browser)
  - org-parser (ClojureScript) based on instaparse (ClojureScript)
    - built with instaparse (seems like a mature parsing toolbox)
    - written in ClojureScript (should be compileable to JavaScript and reuseable in other apps, need to explore this)
    - implemented through expression of *BNF grammar* (a practical abstraction for the parsing problem)
    - developed by 200ok.ch (respected consulting firm with plenty of Org and ClojureScript experience)
- implement own Org parser
  - from scratch (too expensive, not core business, little value to be added to project)
  - in unified ecosystem tooling (implementation of large Org syntax would introduce a lot of work that doesn't directly add value to the project)
#+end_src

Keep single sources of truth

When any topic needs to be documented, find the one place where most will think to look for this information.

For a software project, this will be the git repositories or a more general architecture document in a dedicated knowledge base or another repository.

For a product idea, this will be the place were such ideation typically happens like a product management or project management tool.

Try to avoid replicating information because synchronizing multiple sources is a hard chore. Think: DRY!

Be creative and brief in documenting

We don't all process information the same way. When documenting information consider the following modalities:

Write in a manner that feels natural to hear such that folks using TTS (text-to-speech) tools can follow along.

Since search mostly functions through text, try to accompany every non-text artefact (e.g.: video, diagram, photograph, audio snippet, etc.) with human-readable description.

Since we don't all parse information best through text alone, try to provide diagrams when possible for those who need visual cues. Complement your diagram entries with sufficiently descriptive alt-texts or summaries such that the idea within the diagram is communicated even if the summary is read without awareness of the image. Do the same for any non-text artefact that you may add to a document.


comments

With complex diagrams, it may be easier to define high level