Discussion: Unify pages and blocks


Make everything truly a block.
Substitute page-tags, page-property of simple, advanced queries and other page-related things by block-operations, resolving inconsistencies between page and block.

Intro / Issue

Logseq has the “block” as smallest unit of thought, which is great. In addition, users and developers currently also need to take care of a different concept called “pages”.

Pages are often described as persistable blocks, which are stored as markdown files in the filesystem.

Unfortunately, I have experienced inconsistencies between pages and tags in the user interface (~ one month testing time). This post might serve as point of reference and collection for other related problems, please let me know here. I’ll describe two found issues:

Minimal example

My Page.md:

tags:: mypagetag

- parent #myparenttag
        - child #mychildtag

Issue 1: Query with page-tags vs block tags

Both page-tag (via tags:: mypagetag) and blocktag/page link (#myparenttag, #mychildtag) should be tags and uniformly queried. This is not the case currently (assuming otherwise empty graph):

{{query(and [[mypagetag]] [[mychildtag]] ) }}

→ 0 results

{{query (and (page-tags [[mypagetag]]) ([[mychildtag]]))}}

→ 1 result

From user perspective, it is confusing to differentiate between page-tags and normal tags/page links.

Issue 2: Linked reference filter inconsistency

Going to mypagetag page and inspecting the filter at bottom does not show #myparenttag or #mychildtag in the available items to choose from:



Going to mychildtag will at least show containing page name “My Page”, but not its tag “mypagetag”:


→ Incosistent browsing, depending on which tag you searched first and filtered second


Not sure, if above issues can be easily fixed. But to simply further ongoing development, I would like to suggest further decoupling of the persistence layer, getting rid of page in the UI.
Here is a rudimentary illustration:

Users (UI) should not need to deal with pages. A mapping layer can act as “glue” between pages and blocks, also minimizing breaking changes, so that current filesystem approach is retained.

This mapping layer might provide information like:

  • map page of filesystem to root block for query and other operations
  • find containing page of any given block (1)
  • get all contained blocks of page (2)

Further advantage: This allows to easily switch persistence layer from file-system to SQLite, EDN, or something different.

What also might get easier to implement

  • being able to have block as favorite in sidebar instead of just pages
  • Instead of using complex file names for Logseq namespace, just use a block to represent hierarchy
  • More consistent page and block title:: property, maybe even block aliases (?)


In an ideal word, there is no difference between pages and blocks from a user experience(UX) perspective - pages just take on the duty of saving notes on filesystem.

Abstracting away the storage to the edges of the system might ease up developers’ life as well. If you already got in touch with the Tana app, their approach is straight-forward in this direction: “Everything is a node”.

I think this would be a good time for optimization, as the app is still in Beta status. Feel free to correct me otherwise, if there should something wrong here.

As last point, let me emphasize I love logseq. Please take this as constructive criticism and just an idea to make overall product better.


Related discussions

@venture-comp this is a very clear and well-presented write-up!

I think the ideas on unifying blocks and pages are very interesting.


I like the expression “everything is a node”. Sounds a lot like “everything is a block”, but “even a relation is a block” is less understood than “even an edge is a node”. Or at least, I think so… Do you know what I mean?

As for the pages, I thought they were treated as blocks, as a type of block, but now I understand that this is not exactly the case, since they cannot be in a hierarchy, they are all at the root. That’s why I think that if everything is a block or a node, a block or a node should be able to be anything, including not only configuration files, but even the plugins or the application code itself, forming all part of the graph… Call me crazy.


I think here the issue is more about simple queries. I hope that once the query builder is implemented, its UI will made it clear how to query for tags, page-tags or both.

I don’t think blocks and pages will be revisited at this point…

Think about pages as special blocks that can’t have content but only children blocks and that have a title; and you can reference them with just their title and not an ID.

And then add that the graph view displays pages as nodes and references as relations.

1 Like

It doesn’t seem like a simple matter of queries or output templates to me.

The approach of a mapping layer between the file system and the logical domain, supposes an architectural proposal with very interesting implications, beyond this specific case.

This whole thread doesn’t deal at all with the fact that pages have a title you can use to reference them and that pages are nodes in the graph view.

Mark my words: Tana’s “everything is a block” approach will be a shoot in their own foot.

Perhaps the fact that we are dealing with two graphs, the one of the DB and the one of the graph visualization, that creates some confusion.

Regarding the “everything is a whatever” approach, I take note of your words, but I also wonder why you should say it, because I don’t know Tana, but I understand that you also think it’s a bad idea for Logseq, but I still don’t know why.

Partly due to my limitations, partly due to the fact that in your answer, this time, you don’t provide any arguments to support your statement.

This exactly is the problem with pages and what probably many new users confuse. They are different from blocks:

  • When tags:: mypagetag is assigned to a page - let’s also name it root block here -, I expect this tag to be inherited to all childblocks. An ordinary child block has parent/child inheritance, so it gets all parent tag/page links automatically. But this is not the case with pages, as seen in issue 1.

  • I expect the filter results of page tags to be consistent with the ones of ordinary block tags. Again not the case, see issue 2. Compare the findings of issue 2 with the results, when going to #myparenttag or #mychildtag and click on its filter - there will be more tags to narrow to.

Pages can also have tags and properties.
And it would be awesome to reference blocks by their title name as well! Imagine you would be able to write Grandparent/Parent/My child block to quickly reference arbitrary nested blocks - what today is possible only with page namespace.

This whole thread doesn’t deal at all with the fact that pages have a title you can use to reference them and that pages are nodes in the graph view.

According to Tienson Qin, non-page blocks do have a title - it’s the one line you see as link, when using block references.

Question: Do I miss an argument here, which justifies that pages are kept so differently, that we get confusing problems in the user interface and need to partition the application logic in both pages and blocks (aka page-tags etc.)?

Yes, pages can be persisted. But domain driven design tells us, it’s not a good idea to let core logic or user interface (queries,filtes, etc.) depend on the type of storage. It seems to me, pages are just a storage mechanism.

Concerning graph:
Page = root block, so we might think of graph widget currently as displaying all root blocks and their connections. In future, this could be even enriched with more block details.

Mark my words: Tana’s “everything is a block” approach will be a shoot in their own foot.

Don’t have a Tana account, so I cannot fully understand why even their application settings are a node. The sentence “everything is a node/block” might be ambigious on its own, so let’s keep it simple: it’s about pages vs blocks, and keep everything intuitive, consistent for users and easy to maintain/expand for devs.

I hope that once the query builder is implemented, its UI will made it clear how to query for tags, page-tags or both.

Query builder is a cool idea! But we should get the fundamentals right first.

1 Like

Block content is supposed to be updated often and that would break the reference by title that you want. Currently when you update a page title, all references to it are updated. Of course we can’t do this with block content since it’s updated so often. This is why blocks have IDs to reference them.

I can’t disagree more. Apple does this with iOS by hiding the file system and now we have children that have no idea of what a file is. It’s important to keep the user aware of the file system because it’s a very powerful way to manage data independently from the application. Logseq does already a great work by reflecting its data structure (pages, blocks etc) into Markdown files.

It’s about locking users into their product. Since Logseq edits Markdown files live on the user file system, Logseq is a tool before being a product and you can’t beat standards like files and Markdown syntax with a proprietary online service.

Your concerns are more about UI/UX than Logseq’s data structure and storing mechanism.

You can’t expect such fundamental chances in Logseq at this point… on the other hand, I discussed this query builder mockup two days ago with Logseq UX designer, since it could be the next focus once whiteboards and sync are ready:

Sorry, I have the feeling we are talking a bit past each other. Let’s concentrate on the presented two issues as main point.

These issues might be more UI/UX related, but existence of things like page-tags and page-properties is an indicator for me, that page currently plays an overall bigger role in the system, which is unneeded.

I celebrate logseq to be opensource, offline-first and using plain markdown files.
In fact this is the main reason why I prefer it over Tana.

Do you have a proposal that is not about redesign Logseq fundamentals, since they are not going to change now?

Well, we should let the community vote for all needed features (as usual). And core contributors, which are actually more knowledgeable with the code base, decide if a change is too “fundamental” and out of scope.

It’s not how it works

Wow, it seems that you are saying that there is an authority that dictates what is appropriate or what is not appropriate to discuss or share. I am waiting, so, to receive the appropriate guidelines that reward me with the privilege of being part of this community, as if the code license were just a piece of paper without any kind of political implications.

In any case, I think I’d better go lurker. When I better understand how this works, I’ll see what to do.

I’m saying that using a specific problem (page-tags that doesn’t play well with simple queries) to propose such a drastic change (unifying blocks and pages) is an unjustified logical leap and it’s a waste of your time.

If you want to contribute, you have to make an effort to understand more deeply before writing.

Hmm, I personally don’t see the need for unifying pages and blocks, nor any additional benefits.

There are several plugin APIs that make it easier for a plugin developer (at least in my point of view) because there are distinctions between pages and blocks.

I personally would not vote for unifying pages and blocks at this point.

1 Like

Instead of going “lurker” reply to my objections like “you can’t use the title (first line) of a block to uniquely reference it”.

Since OP can’t reply to those objections they just remarked their right to discuss whatever they want, that is a childish way to end a discussion.

@alex0 I’d suggest you calm down a bit. Your writing style has become too passive aggressive to continue conversation at this point.

You could have made some effort to comment or hint me on the concrete listed issues, e.g. if there already a bug request. By the way: this feature request evolved from other discussions, see OP bottom.

Instead you decided to speak like a single authority for the community, that feature XY is “not going to change”. And all that (please correct me otherwise) without technical contribution background on the Logseq code base according to GitHub contributers’ insight - quite arrogant.

At the end of the day, this forum is a place for discussions, right? These have been my suggestions from a non-(yet)-contributor perspective. If af the end of the day, there is common agreement to handle the two listed issues as bug request for now, I am totally fine with it. If it moves a developer to think further about this approach similar to one of the Tana app ideas, that’s cool too.

Btw. I am curious: you still haven’t given any arguments with regard to


You are the one saying that you want to discuss but you are avoiding my objections, so instead of provoking, reply to them.

We were at this:

How do you uniquely reference blocks by their “title” (first line) if:

  1. More blocks can have the same first line and I think you don’t want to reference them with a/very/long/path starting from uniquely titled root blocks.
  2. Block content is supposed to be edited often and you should make it clear somehow to the user that editing the first line of a block would result in Logseq updating all the other blocks referencing it (basically the current UX when updating a page title).