quartz
quartz copied to clipboard
feat(open-graph): Add ability to generate OG images + further OG support
After finally getting around to writing the docs, the open graph PR is now ready for review.
A detailed overview over how this works can be found in the docs now, but in summary, this enables users to automatically generate OG images with a lot of customisation options (even the ability to provide your own html/css satori component via config!)
This uses satori to generate an svg from html/css markup and sharp to convert it to .webp
with some additional compression.
As discussed, this feature is disabled by default (so is opt-in). I only have figures from 4 months ago when I implemented this PR, but the total file size for all images for the entire docs folder was just 960KB, with an average of around 19KB per image.
This PR also adds some further Open Graph configuration support by adding frontmatter properties to override description/image (with aliases to support the matching ones from obsidian publish).
If you have any questions, improvements or remarks, please let me know :)
small ask. Can you rebase this onto main so that it would only be one commit 😄 Probably a bit easier to cherry-pick and test out the changes :)
small ask. Can you rebase this onto main so that it would only be one commit 😄 Probably a bit easier to cherry-pick and test out the changes :)
its ok, all PRs are squashed before merging anyways :)
small design nit before i look at this further, can we get a layout more like this?
Sure, will change the default layout :)
Few questions about how you want this implemented
What about the logo? Should this use the icon.png
from the static folder? (could use to some funky looks if users have icons that differ greatly in size/aspect ratio). Or should this always use the quartz icon statically? Should users then also be able to further customise what icon is used here, or is relying on the site icon fine
The font size for the header size seems pretty big, from my testing, this was already pretty hard to fit with longer titles. How do you want to handle cases for long titles? Right now, I have a "breakpoint" variable, and if the title exceeds that length, it gets turned into a smaller font size. Alternatively, we could multi-line the title (tho that could look weird quickly next to the icon) or cut off the title with "..." if it gets too long.
Little suggestion: allow to change the default image path for frontmatter, so I can use content/img
instead.
Little suggestion: allow to change the default image path for frontmatter, so I can use
content/img
instead.
Def something that can be improved in the future, but probably better to change this in a separate PR, as this one already has over 1000 line changes and is a lot to review at once (for sure want to add something this tho, alongside the ability to add external urls for images :) )
Little suggestion: allow to change the default image path for frontmatter, so I can use
content/img
instead.Def something that can be improved in the future, but probably better to change this in a separate PR, as this one already has over 1000 line changes and is a lot to review at once (for sure want to add something this tho, alongside the ability to add external urls for images :) )
No problem, i will wait for the approvable and make an additional update right after!
Little suggestion: allow to change the default image path for frontmatter, so I can use
content/img
instead.
For this particular feature, we should use the same as Obsidian : https://help.obsidian.md/Obsidian+Publish/Social+media+link+previews#Image
Sure, will change the default layout :)
Few questions about how you want this implemented
What about the logo? Should this use the
icon.png
from the static folder? (could use to some funky looks if users have icons that differ greatly in size/aspect ratio). Or should this always use the quartz icon statically? Should users then also be able to further customise what icon is used here, or is relying on the site icon fineThe font size for the header size seems pretty big, from my testing, this was already pretty hard to fit with longer titles. How do you want to handle cases for long titles? Right now, I have a "breakpoint" variable, and if the title exceeds that length, it gets turned into a smaller font size. Alternatively, we could multi-line the title (tho that could look weird quickly next to the icon) or cut off the title with "..." if it gets too long.
- Let's try to use
icon.png
, this is the favicon anyways so safe to assume it is close to 1:1 - Breakpoint seams reasonable :)
Could you rebase to fix the merge conflict?
I'll take a look at changing the default image, fix the merge issues and address your review today or tmrw hopefully :)
Should we name these based on slugs instead of path?
Oh and also space also needs to be escape afaik
Should we name these based on slugs instead of path?
Oh and also space also needs to be escape afaik
I don't think slugs have to be globally unique, so using slugs doesn't really provide a benefit and would just require an additional step of making sure every file name is unique. By using paths, the OS already guarantees uniqueness if we take the full path.
For spaces, do we need to escape them? On windows and mac it works just fine, not sure if there are some Linux distributions that can't handle spaces in file names.
Still haven't gotten around to fixing everything from the review up bc i got sick, but hopefully soon now :)
no worries wish you a speedy recovery! let us know if there is anything we can help with.
@benschlegel any updates on this PR?
been some really stressful weeks, i probably have a few hours tomorrow to take a look and then some more starting next wednesday, just fyi but hopefully finally get some free time to take a look
We will have to decide whether we want to generate this on demand or dump everything pre-serving time.
pre-serve will cost cold start a bunch, reload with this one is essentially 30s every reload trigger ( for a 200 files vault, can't imagine for vault that is 5k+)
I think probably best if the components is async, then it would help creating this on demand (which is probably better)
current solution:
if (cfg.generateSocialImages && !ctx.argv.serve) {}
Really excited for this one! Appreciate the effort, guys 🙌
We will have to decide whether we want to generate this on demand or dump everything pre-serving time.
pre-serve will cost cold start a bunch, reload with this one is essentially 30s every reload trigger ( for a 200 files vault, can't imagine for vault that is 5k+)
I think probably best if the components is async, then it would help creating this on demand (which is probably better)
current solution:
if (cfg.generateSocialImages && !ctx.argv.serve) {}
This is an area that can be improved for sure, currently, all images are generated on startup (but async, so it doesn't block). Maybe this is an improvement that could be made in a future PR, as it's already hard to keep track of every review here (and i still have a lot to go through from jacky). Since this feature is disabled by default anyways, I don't think this is too critical for now. I know I personally don't have enough free time atm to test out your proposed changes in context of all possible config options and other quartz config, but if you do and it all still works as expected, we can also add this now
I think this has to do with us cleanup the public files everytime for hot reload, which means each hot reload will recreate the webp everytime.
I don't know if async helps or do anything here.
Also I think my comments previously is probably because I move the image generation to componentResources.ts, hence the blocking.
hi @benschlegel, sorry for the ping, if you still want to work on the PR lmk, or I can help with continuing your work here.
hi @benschlegel, sorry for the ping, if you still want to work on the PR lmk, or I can help with continuing your work here.
Hey, no worries. Uni has been going crazy and I didn't really have time to work on this until now, but semester is over now and I should get some time again soon. If you need this sooner or want to do it yourself, that works too, but I don't think too much is missing to get this finished now.
no worries at all really. I have implemented this on my side, this is rather bringing this to Quartz.
This would be such a killer feature. Thanks for putting the work in! ❤️