Discussion: Unify pages and blocks

What if there were just blocks aliases but a plugin let you assign them programmatically to selected blocks?

For example:

- Foo
  alias:: [[Foo]]
    - Qux
      alias:: [[Foo/Qux]]
- Bar
  alias:: [[Bar]]
    - Qux
      alias:: [[Bar/Qux]]

Hmm not too excited about this :slight_smile: . This looks a bit redundant and mixes page and block entity.

I think, easiest approach is to just gradually let each UI feature adapt more to block-level scope. And make block references ((1234)) more powerful. Then nothing new needs to be learned or changed by users.

Understood and I see why you want to use blocks’ tree structure to reference blocks. It would also make sense to be able to refer to specific children with a relative path.

My proposal of using aliases is basically use them as ad-hoc bridges from the strict namespace of pages to the fluid structure of blocks.

It could also be used in place of my previous idea of using title:: property, with the advantage that the user already know aliases. It would work like this:

  • assign an alias to a block: alias:: Block 1
  • reference that block using a [[wikilink]]: [[Block 1]]<
  • in the Graph View it appears as Block 1 just like pages
  • you can use [[Block 1]] as a property value
  • queries just work as always by mentioning [[Block 1]]
  • the only difference is that when you click on [[Block 1]] you will be pointed to that block instead of a page

I think this could at least unlock the Tana-like workflow, making us free to use nodes that are not pages/root blocks/MD files and that are in a tree structure.

I don’t have better ideas than programmatically assign aliases using maybe a plugin to emulate what you want, sorry.

But maybe we could have a syntax like ((./Title)) that could let us point to a child block, though the the user would take care of not breaking links.

Something like:

- Title of an article
   references:: ((./References))
   ...
   - References

So that if this block appears as a result in a query table, you can click on References to go directly to its child block.

Though this could be done just using manually the block aliases mentioned above.

Your solution might work as short-term workaround, but will create technical debt for the app (my opinion).

The fundamental issue is unneeded discrimination between page and block on a UI and core logic level .

The described errors in OP are a manifestation of this design limitation. And our proposals/features could probably be implemented way easier, if blocks and pages wouldn’t be distinguished this much in the UI.

I hope developers get more attention on this, to ease up further development and make it a strong competitor to Tana feature-wise.

Block aliases or not, the fundamental issue is:

  • Pages have unique names
  • Blocks have UUIDs
  • We need a way to reference blocks in queries and properties that work as good as [[page]] references
  • And eventually display certain blocks in the Graph View
1 Like

The first point is a constraint of the file system (unique names). The second is a constraint for the domain logic (unique block IDs). This might be done by assigning an UUID to every block, incl. root block (=page), so there is a mapping of page name to page UUID.
What about an id:: property at the top of every page, akin to tags::, same as current block ids?

Alternatively we could use string ID and keep uniqueness of pages via filename, but that probably has performance issues.

Yes. + Showing block references in the “Linked References” widget at each page bottom would be quite useful.

No, this is the key, you think we have pages because of files on the file system, while we have pages because we want [[wikilinks]] i.e. we want to turn words in our paragraphs into references by simply adding [[ ]]. Storing pages as files is a consequence, not a cause.

Now I understand while you brought the file system in this discussion…

Logseq is not constrained by the file system at all and it already abstracts it away with its DB.

I hope now you understand why I proposed block aliases, because we would be able to define a new node from context instead of creating a new page.

Think more about it, block aliases are all we need: if you want a block to be treated like a page, assign an alias and use that as [[handle]] in properties and queries.

Good hint, seeing your point with “just quickly typing it”, for example as well with an external editor. But I am asking myself if this a contradiction at all. [[ ]] could be the syntax for uniquely named blocks, (( )) for blocks with possible duplicate titles and needed technical ID - no change again.

What has become more clear and important to me - and I think we both agree on this - , is that Query, Linked references + filter and all these great UI features in Logseq need to work on block-scope. And they should behave consistently (take page-tags/tags: for example), no matter if we keep pages or not.

Yes and they choose to call those named blocks “pages”… but the issue is that pages can only be root blocks (and this is what block aliases are meant to fix) and that they enable different features in the UI (just because devs decided to do so).

Yes and I have an idea on how block references (with ((UUID)) and [[aliases]] ) could be presented:

  • At the moment a block with references has a count on the right that you can click to list references. I think it could instead show two (virtual) additional children blocks: Linked References and Unlinked References that when expanded show references that can be edited just like we do at the bottom of pages.
  • When focusing the view to a particular block by clicking the bullet point, the same Linked and Unlinked References appears at the bottom, just like in a page.
  • In both cases there would be a way to filter references as we do now at the bottom of pages.

Additionally, I hope that devs will hear the suggestion I made to the designer about replacing Linked and Unlinked References sections with fixed queries where you can add additional filters with the future query builder.

So basically reuse UI components as much as possible.

As said, I am not a fan of this idea:

  • A page is a block with additional unique title constraint (*), but in the end still a block (superset or extends relations if you will with object oriented programming). There should be no need to artificially promote a block to page, if most of the logic operates on block as common type.
  • If I understood this, we need to manually prepare this block and looks to be repetitive work

Interesting idea, I like it.

If everything internally uses queries, that would reduce our block-scope issue to … queries, hence more easy to fix :slight_smile: I’d like to have some customizable footer for pages as well, where you can place more queries - similar to :default-queries in the journal.

And we haven’t spoken of transitive queries yet. John Doe -> Author -> Person. Then on page Person query everything which is transitively linked, like page John Doe. That as custom query at page bottom would be cool.

I am out for today. Cheers!


(*) thanks again for your point, this indeed is important for easy typing links in the editor. Even if Logseq provides auto-complete for page IDs like [%title%](<page-id), creating links in an external editor would be more difficult. Btw: Haven’t we already spoken of this with regards to blocks and their titles?

Personally I would only show those (un)linked references when you zoom into a block (as it is only referenced to that specific block) and not the larger set of blocks (aka page). A small indicator to indicate that there are references to this block in the first place is fine.

UPDATE : I wrote to soon :slight_smile: … seeing you next bullet. But I do not like the expanded show when not being zoomed in into the block.

To be clear, when not “zoomed” it would look just as it is now, but:

  • when clicking on the number of references they are not displayed in a popup as it is now but as “virtual” children blocks. EDIT: I was wrong, there is no popup anymore, it is already as I desired!
  • when clicking on the bullet point the view “zooms” on it as it is now but additionally at the bottom there are the references like on pages

The difference is due to the nature of file storage (& performance limitation)
Hopefully the database-based storage can remove the barrier. It’s under development.

2 Likes

I think the concept of “pages” comes from the need to have references using [[words]] and saving them as files is a consequence (but not strictly needed).

Even with a different storage method, I don’t think the concept of pages (and [[wikilinks]]) will cease to exist but correct me if I am wrong.


On the other hand what started this discussion is more about differences in UI/UX for pages and blocks that appear arbitrary, than a need to remove the distinction between pages and blocks.

(Edit: for example the issue reported by OP is about Simple Queries looking for references in block content and path, but not considering page-tags:: values too, that is something that would definitely makes sense from the user point of view).

@venture-comp let me stress again that the term “unify” in the title is misleading, what you are looking for is more consistency.

“Makes pages and blocks more consistent” looks like a better title to me, that reflects what’s discussed here.

1 Like

Thanks for the info!
I have noticed the post has been marked with “estimate-very-large”, which is fair enough. Do you think the main described issues #7592 and #7978 can be fixed sooner - or are they are out of scope and we need to wait for database design first?

@alex0 it makes more sense then to mark OP as solved with this post I guess.

The two issues seem to be more complex to change than I hoped :frowning: . Developers’ statement:

It requires large effort due to the inner implementation of query

Feeling inclined to say: Only use block properties for now.
Omit any page-properties including tags::, if you need to search for multiple page references in a consistent manner with queries and filter widget.

I am currently testing a smallish Python script, which auto-converts all page-properties to block-properties. Disadvantage: There is an additional indention inside the page (for block inheritance). Advantage: searching and filtering works. Let me know, if there is any interest for discussions.

I have not this issue because I use page properties only to find pages.

Instead in pages I use [[references]] in section headers and below I place the content.

If you are looking for a workaround try to ask for an Advanced Query in #queries on Discord.

Recently I got a query that looks for properties in parents (basically how [[references]] appear to be “inherited” by children, but for properties).

This is basically the behavior you are looking for but for pages (because with pages you are forced to use properties).

Interesting. Guess that is the beauty of Logseq - everyone has own, unique workflows.

I heavily rely on combining pages for quick searching, like [[logseq]] and [[feature]]. That might be a simple query (and [[logseq]] [[feature]] ). But you’ve got a problem, if any of these links are declared as page tags:

  • Was it (and [[logseq]] [[feature]] ) ?
  • Or (and (page-tags [[logseq]]) [[feature]] ) ?
  • Oh fu**, it was (and (page-tags [[feature]]) [[logseq]] ) .

Same with the filter - not predictable at all. You can’t be sure to not have missed a result.

I know, advanced queries take it to another level. But that all is too cumbersome. I yet have to find an app that can create links and pages easiert than Logseq - [[foo]] is all it takes. If something is intuitive, quick and simple to do, you enjoy doing it more often. Same would be nice for searches and filter.

Your proposed query wizard certainly seems to be a good compromise. In the end, there is still a flaw in the current query implementation we should fix, so everything works consistently. E.g. a query builder doesn’t help for the UI filter, or if you are already used to do your stuff with simple queries etc.

1 Like

I understand your need, but on the other hand it is very natural to do so:

Logseq.md
type:: [[Application]]
tags:: [[PKM]]

- [[Features]]
  - ...
- [[Plugins]]
  - ...
{{query (page-tags [[PKM]])}}
{{query (and [[Logseq]] [[Features]])}}
1 Like

This may feel natural to you, but is not my exact workflow.
Natural is to have freedom of choice how to organize things, without surprises.

Assuming we would organize notes like in your example with a template, even then it would be hard to keep notes consistent.

(Edit) Regarding example: At one point in the future, you’d like to find out content about PKM features and search for {{query (and [[PKM]] [[Features]])}}. Nothing found, if you can’t remember, that PKM is a page tag - ouch.

1 Like