logseq post
This commit is contained in:
parent
10426919e1
commit
0c2ac5e521
13 changed files with 1249 additions and 48 deletions
|
@ -1,13 +1,14 @@
|
|||
import { defineConfig } from "astro/config";
|
||||
import mdx from "@astrojs/mdx";
|
||||
|
||||
import sitemap from "@astrojs/sitemap";
|
||||
import { astroImageTools } from "astro-imagetools";
|
||||
|
||||
import { remarkReadingTime } from "./plugin/remark-reading-time";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: "https://mzhang.io",
|
||||
integrations: [mdx(), sitemap()],
|
||||
integrations: [mdx(), sitemap(), astroImageTools],
|
||||
markdown: {
|
||||
syntaxHighlight: false,
|
||||
remarkPlugins: [remarkReadingTime],
|
||||
|
|
1061
package-lock.json
generated
1061
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,7 @@
|
|||
"@astrojs/rss": "^3.0.0",
|
||||
"@astrojs/sitemap": "^3.0.0",
|
||||
"astro": "^3.0.3",
|
||||
"astro-imagetools": "^0.9.0",
|
||||
"fork-awesome": "^1.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
|
|
|
@ -4,25 +4,29 @@ const posts = defineCollection({
|
|||
type: "content",
|
||||
|
||||
// Type-check frontmatter using a schema
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
date: z.date(),
|
||||
schema: ({ image }) =>
|
||||
z.object({
|
||||
title: z.string(),
|
||||
date: z.date(),
|
||||
|
||||
// Transform string to Date object
|
||||
pubDate: z
|
||||
.string()
|
||||
.or(z.date())
|
||||
.transform((val) => new Date(val))
|
||||
.optional(),
|
||||
updatedDate: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((str) => (str ? new Date(str) : undefined))
|
||||
.optional(),
|
||||
// Transform string to Date object
|
||||
pubDate: z
|
||||
.string()
|
||||
.or(z.date())
|
||||
.transform((val) => new Date(val))
|
||||
.optional(),
|
||||
updatedDate: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((str) => (str ? new Date(str) : undefined))
|
||||
.optional(),
|
||||
|
||||
tags: z.array(z.string()),
|
||||
draft: z.boolean().default(false),
|
||||
}),
|
||||
heroImage: image().optional(),
|
||||
heroAlt: z.string().optional(),
|
||||
|
||||
tags: z.array(z.string()),
|
||||
draft: z.boolean().default(false),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { posts };
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
title: Thoughts on Logseq
|
||||
date: 2023-08-31T13:57:29.022Z
|
||||
tags:
|
||||
- organization
|
||||
- logseq
|
||||
draft: true
|
||||
---
|
||||
|
||||
After working for quite a bit I like to catch up with some friends from time to
|
||||
time, when I made a shocking discovery -- most of them don't really use a
|
||||
calendar of any sort to manage their lives.
|
||||
|
||||
For a while I've always wanted a kind of personal information manager: something
|
||||
that would put all my information in one place and make it easy for me to query
|
||||
across apps.
|
BIN
src/content/posts/2023-08-31-thoughts-on-logseq/calendarHero.png
Normal file
BIN
src/content/posts/2023-08-31-thoughts-on-logseq/calendarHero.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 984 KiB |
119
src/content/posts/2023-08-31-thoughts-on-logseq/index.md
Normal file
119
src/content/posts/2023-08-31-thoughts-on-logseq/index.md
Normal file
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
title: Thoughts on personal organization
|
||||
date: 2023-08-31T13:57:29.022Z
|
||||
tags:
|
||||
- organization
|
||||
- logseq
|
||||
|
||||
heroImage: ./calendarHero.png
|
||||
heroAlt: pastel colored stationery background with a bunch of calendars and personal organization tools in a crayon drawing style
|
||||
---
|
||||
|
||||
After working for quite a bit I like to catch up with some old friends from time
|
||||
to time, when I made a surprising discovery -- many of them don't really use a
|
||||
calendar of any sort to manage their lives. Tracking something that happens more
|
||||
than a week into the future is generally out of the picture.
|
||||
|
||||
But I understand. Putting events into a calendar is kind of a chore. Calendars
|
||||
that are [standards-compliant][3] are still primarily use email for the most part
|
||||
(sending invites, updating times, etc.) and calendars that aren't
|
||||
standards-compliant won't be compatible between different people unless they're
|
||||
using the same service.
|
||||
|
||||
[3]: https://datatracker.ietf.org/doc/html/rfc5545
|
||||
|
||||
The personal management story has always been kind of fragmented. Calendars are
|
||||
supposed to manage the entire picture of my personal schedule, yet they only see
|
||||
a small slice without more information. The only things calendars can see
|
||||
automatically with no intervention on my part are emails that happen to include
|
||||
.ics files.
|
||||
|
||||
> I'm sure Google or Apple could probably ritz up their mail servers to scan text
|
||||
> and try to see if there's events without there being an actual .ics file, but
|
||||
> that's missing the point. The vast majority of people I associate with rarely
|
||||
> sends email events anymore.
|
||||
|
||||
## Journals
|
||||
|
||||
For a while I've always wanted a kind of personal information manager: something
|
||||
that would put all my information in one place and make it easy for me to query
|
||||
across apps. When I embarked on this search I wouldn't have thought that the
|
||||
most promising tool would end up being a journaling app.
|
||||
|
||||
(by journaling app I mean something like [Logseq], [Obsidian], [Notion],
|
||||
[Workflowy] or [the][roam] [million][joplin] [other][craft]
|
||||
[similar][stdnotes] [apps][bear] that allow you to write some markdown-ish
|
||||
content, store it, and then never look back at it again)
|
||||
|
||||
[logseq]: https://logseq.com
|
||||
[obsidian]: https://obsidian.md/
|
||||
[notion]: https://www.notion.so/
|
||||
[workflowy]: https://workflowy.com/
|
||||
[roam]: https://roamresearch.com/
|
||||
[joplin]: https://joplinapp.org/
|
||||
[craft]: https://www.craft.do/
|
||||
[stdnotes]: https://standardnotes.com/
|
||||
[bear]: https://bear.app/
|
||||
|
||||
The world of journaling apps is vast but undiverse. Most of the apps just have
|
||||
the same features others do, minus one or two gimmicks that makes it a ride or
|
||||
die. But there's one important feature that I have started looking out for
|
||||
recently: the ability to attach arbitrary metadata to journal entries and be
|
||||
able to query for them.
|
||||
|
||||
I think the community is starting to realize that these journals are really just
|
||||
databases, and extracting structured fields is extremely important if you want
|
||||
any kind of smart understanding of what is being journaled.
|
||||
|
||||
[Logseq], the app that I've settled on, is backed by a [Datascript] store and
|
||||
exposes a lot of this functionality to you as a user. It allows you to query
|
||||
directly on properties that you write into your daily journal or any other page,
|
||||
for example like this:
|
||||
|
||||
```
|
||||
- ... other content ...
|
||||
- minicross:: 34
|
||||
- ... other content ...
|
||||
```
|
||||
|
||||
I use this on my daily journals to track how long it takes me to do the [NY
|
||||
Times daily crossword][minicross]. But Logseq is able to index this property in
|
||||
particular and let me query on it later:
|
||||
|
||||
[datascript]: https://github.com/tonsky/datascript
|
||||
[minicross]: https://www.nytimes.com/crosswords/game/mini
|
||||
|
||||
![performing a query in logseq](./logseqQuery.png)
|
||||
|
||||
I can write todo items inline in my journal and find them all at a time as well.
|
||||
As an example, here's all of the todo items that I've tagged specifically with
|
||||
#read:
|
||||
|
||||
![reading list in logseq](./readingList.png)
|
||||
|
||||
The fact that it truly is a database means I can start piling things in here and
|
||||
automatically perform data extraction for a more complete picture of my daily
|
||||
life. In the future I'd like to do dumps for my sleep and health data as well
|
||||
and have Logseq be my ultimate source of truth.
|
||||
|
||||
I've also started developing a [calendar plugin for Logseq][2] that will have
|
||||
the ability to display numerical data using various visualizations by using the
|
||||
[D3] library.
|
||||
|
||||
[d3]: https://d3js.org/
|
||||
[2]: https://git.mzhang.io/michael/logseq-calendar
|
||||
|
||||
## Privacy
|
||||
|
||||
Because people are dumping so much of their lives into journals, it's absolutely
|
||||
crucial that boundaries are clear. Without control, this would be a dream come
|
||||
true for any data collection company: rather than having to go out and gather
|
||||
the data, users are entering and structuring it all by themselves.
|
||||
|
||||
End-to-end encryption is a feature that ensures data is never able to be
|
||||
accessed by your storage or synchronization providers. Of course, end-to-end
|
||||
encryption is [not possible unless the entire software is able to be scrutinized
|
||||
by the user or community][1]. Do careful research before deciding who to trust
|
||||
with your data.
|
||||
|
||||
[1]: /posts/2021-10-31-e2e-encryption-useless-without-client-freedom
|
BIN
src/content/posts/2023-08-31-thoughts-on-logseq/logseqQuery.png
Normal file
BIN
src/content/posts/2023-08-31-thoughts-on-logseq/logseqQuery.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
BIN
src/content/posts/2023-08-31-thoughts-on-logseq/readingList.png
Normal file
BIN
src/content/posts/2023-08-31-thoughts-on-logseq/readingList.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 189 KiB |
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import PostList from "../components/PostList.astro";
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
import { join } from "path";
|
||||
import { join, dirname } from "path";
|
||||
|
||||
const currentUrl = Astro.url;
|
||||
---
|
||||
|
@ -9,5 +9,5 @@ const currentUrl = Astro.url;
|
|||
<BaseLayout>
|
||||
<h2>Blog</h2>
|
||||
|
||||
<PostList basePath={join(currentUrl.pathname, "posts")} drafts="only" />
|
||||
<PostList basePath={join(dirname(currentUrl.pathname), "posts")} drafts="only" />
|
||||
</BaseLayout>
|
||||
|
|
|
@ -3,7 +3,7 @@ import "../../styles/post.scss";
|
|||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import { type CollectionEntry, getCollection } from "astro:content";
|
||||
import Timestamp from "../../components/Timestamp.astro";
|
||||
// import BlogPost from "../../layouts/BlogPost.astro";
|
||||
import { getImage } from "astro:assets";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getCollection("posts");
|
||||
|
@ -17,17 +17,33 @@ type Props = CollectionEntry<"posts">;
|
|||
|
||||
const post = Astro.props;
|
||||
const { Content, remarkPluginFrontmatter } = await post.render();
|
||||
const { heroImage: heroImagePath, heroAlt } = post.data;
|
||||
|
||||
let heroImage;
|
||||
if (heroImagePath) {
|
||||
heroImage = await getImage({ src: heroImagePath });
|
||||
}
|
||||
---
|
||||
|
||||
<BaseLayout>
|
||||
<h1 class="post-title">{post.data.title}</h1>
|
||||
<div class="post-container">
|
||||
<h1 class="post-title">{post.data.title}</h1>
|
||||
|
||||
<small class="post-meta">
|
||||
Posted on <Timestamp timestamp={post.data.date} />
|
||||
- {remarkPluginFrontmatter.minutesRead}
|
||||
</small>
|
||||
<small class="post-meta">
|
||||
Posted on <Timestamp timestamp={post.data.date} />
|
||||
- {remarkPluginFrontmatter.minutesRead}
|
||||
</small>
|
||||
|
||||
<!-- <BlogPost {...post.data}> -->
|
||||
<Content />
|
||||
{
|
||||
heroImage && heroAlt && (
|
||||
<div style={`background-image: url(${heroImage.src});`} title={heroAlt} class="hero" />
|
||||
)
|
||||
}
|
||||
|
||||
<!-- <BlogPost {...post.data}> -->
|
||||
<div class="post-content">
|
||||
<Content />
|
||||
</div>
|
||||
</div>
|
||||
<!-- </BlogPost> -->
|
||||
</BaseLayout>
|
||||
|
|
|
@ -65,7 +65,7 @@ a code {
|
|||
}
|
||||
|
||||
blockquote {
|
||||
margin-inline: 14px 14px;
|
||||
margin-inline: 0;
|
||||
color: var(--small-text-color);
|
||||
border-left: 4px solid var(--small-text-color);
|
||||
padding-left: 12px;
|
||||
|
|
|
@ -9,6 +9,16 @@
|
|||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
background-size: cover;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 8px;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.post-container {
|
||||
display: flex;
|
||||
|
||||
|
@ -23,6 +33,11 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
p img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
@media screen and (max-width: 520px) {
|
||||
flex-direction: column;
|
||||
|
@ -153,7 +168,7 @@
|
|||
}
|
||||
|
||||
> p {
|
||||
line-height: 1.5;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
> p > img {
|
||||
|
@ -163,7 +178,7 @@
|
|||
|
||||
.footnotes {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.2;
|
||||
line-height: 1.05;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue