GithubHelp home page GithubHelp logo

platypub's Introduction

Platypub

ALPHA NOTICE: Platypub is still in an early state and is in need of a rearchitecture. Breaking changes imminent.

A blogging + newsletter platform. Platypub is basically (1) a CMS, with (2) integrations for Netlify (for hosting your site) and Mailgun (for sending your newsletter) and (3) an extremely flexible theme system. Platypub can run as a multi-tenant managed service (e.g. as opposed to Ghost/Wordpress, where each user must have their own instance), or you can self-host it or even run it locally. It's meant to combine the convenience of e.g. Substack with the flexibility of a static site generator. I also want to add data import/export integrations, so you can e.g. publish your social media posts on your website, or automatically cross-post your articles to social media.

Platypub is not ready for general use yet. When it is, I'll host a public instance of it (with usage-based pricing and a free tier).

Platypub is built with Biff, a Clojure web framework. If you're a Clojurist and you'd like to contribute, see the roadmap for a list of good first issues.

See also Announcing Platypub: open-source blogging + newsletter tool.

Getting started

Prerequisites:

  • JDK 11 or higher
  • clj
  • Babashka (bb should be on your path)
  • (Optional) API keys for Netlify, S3, Mailgun, and Recaptcha (see config.edn and secrets.env). You can run Platypub without these, but most of the features won't be available.

Run the following:

cp config.edn.TEMPLATE config.edn
cp secrets.env.TEMPLATE secrets.env
cp themes/deps.edn.TEMPLATE themes/deps.edn

Run bb generate-secrets and paste the output into secrets.env. Also edit config.edn and secrets.env as needed.

Then you can start Platypub with bb dev. After you see a System started message, the app will be running on localhost:8080. Once you've signed in, you can create a site, a newsletter, and some posts as described in the default theme setup.

Create a website

  1. Go to Sites and click "New site"
  2. Go to Newsletters and click "New newsletter"
  3. Create the following pages for the new site:
  • One with path: / (home page)
  • One with path: /subscribed (page shown to people after they subscribe to your newsletter)
  • One with path: /about (page linked to in the navigation bar by default)
  • One with path: /welcome and tags: welcome (email sent to people after they subscribe to your newsletter)

Then you can go to Sites and click "preview." If you want to set a custom domain, you'll need to do it from Netlify's website, then update the URL field on the site config page.

Create a custom theme

  1. Copy themes/default to themes/mytheme (or whatever)
  2. Edit/move all the files under themes/mytheme so they use a unique namespace instead of com/platypub/themes/default
  3. Edit the default.clj file (or whatever you renamed it to) and change the :label key at the bottom to something unique.
  4. Edit themes/deps.edn and add themes/mytheme as a local dependency.
  5. Edit config.edn and add the fully-qualified symbol for your theme's plugin var to :com.platypub/themes
  6. Go to Sites -> click on your website, then change the theme setting to your new theme.

While developing your theme, you'll need to do cd themes/mytheme; bb css to make the css file update.

Deployment

You don't need to deploy Platypub to use it. You can run it locally, since any sites you create will be hosted externally on Netlify anyway. However if you'd like to deploy it for convenience, uncomment the :com.platypub/allowed-users and :com.platypub/enable-email-sigin config keys first.

See the Biff docs for deployment instructions.

platypub's People

Contributors

bhlieberman avatar jacobobryant avatar jeffp42ker avatar joerter avatar mtrost avatar refset avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

platypub's Issues

Add a :post/sites attribute to the :post schema

The type should be [:vector :site/id]. Add it as an optional key in the :post schema for backwards compatibility.

Then we need to update the UI. Posts should have an additional field somewhere on the sidebar in the edit post page. There are at least three ways we could do it:

  • use a native html single-select element. (
    (defn select
    ). Even though the schema allows posts to have multiple sites, for now we have the UI support only one site per post. Then we wait to see if anyone actually does ever want a single post to be under multiple sites.
  • Use checkboxes (I don't like the native multiple select element, at least not on desktop)
  • Use a JS multiselect component, like https://sa-si-dev.github.io/virtual-select/

I'm ok with any of those options--I probably lean towards using a single-select element for now.

Also we should update the Posts page to show the sites that posts belong to, similar to how currently tags are listed.

Then we need to update the theme code to use the new attribute. See this line:

((:post/tags post) (:site/tag site)))))
. For backwards compatibility we can continue checking for a match against the :site/tag attribute. We just wrap it in an or and have the other condition be "does the :post/sites attribute match the site's :xt/id".

Investigate options for running theme code in a sandbox

A prerequisite for moving to stage three is we need some way to accept untrusted theme code. Cloudflare's recently announced workers for platforms looks perfect, however it's still in closed beta and I doubt they would give us access. We're not in a huge rush to get to stage three yet, so maybe we just wait until that's available for everyone. (How long does Cloudflare usually take to move features from closed to open beta?) If anyone is interested, it wouldn't hurt to explore other options though. I spent a day looking into this and my conclusion was that besides the Cloudflare thing, AWS Lambda would probably be the way to go (in which case it would be especially great for someone else to take this issue because I have little experience with AWS and prefer to keep it that way). I'm open to other things too.

Whatever we use for the sandbox, we need to be able to zip up the theme folder (e.g. themes/default/), send it to the sandbox, and have it unzip, generate site files, and return them in another zip file. or something like that. And ideally have it be fairly snappy (under 10 seconds is probably acceptable, though the faster the better). If we can let the theme code specify dependencies (such as npm dependencies) and have the sandbox install + cache the dependencies that would be swell. If not, it's probably good enough to start out with if we just have a fixed list of dependencies (like tailwind etc).

Slug value generated from post title would be helpful

When creating a post's slug I typically:

  • copy-paste the title
  • lower-case the words
  • remove apostrophes, special characters
  • replace spaces with dashes
  • add a date representation to ensure it's unique

It'd be helpful if this transformation was available as the candidate slug value once the title is completed.

Replace juice with a jvm alternative

Currently we use Juice, a Node program, for preprocessing emails. Rendering would be faster if we could stick to the JVM. From a quick search a while ago, a few people suggested doing something with JSoup.

Make theme code sharing easier

Move themes/default/common.bb to themes/default/src/com/platypub/themes/common.clj. Make render-site and render-email use require instead of load-file. Make a deps.edn file with {:paths ["src" "resources"]} for the contents. Move subscribe.js, email.css and any other files that other themes might want to use to themes/default/resources/com/platypub/themes/default/. Update render-site and render-email accordingly.

Then custom themes can add the default theme as a dependency and reuse anything in common.clj or resources by depending on com.github.jacobobryant/platypub {:sha "..." :deps/root "themes/default"}. (Need to figure out the right way to do that--if custom themes put that in deps.edn, will it apply when we run render-site and render-email? Do we need to change the way Platypub calls theme code? If needed we can always turn render-site and render-email into one-line bash scripts that call bb with the appropriate dependencies and commands)

Add a file to themes with sample data

If a theme has an input.edn file (i.e. committed to the git repo, not the input.edn file that platypub generates), treat it as sample data. When you create a new site with that theme, populate the db with the sample data. Sample data files will also be useful for doing theme development with ./task dev in the theme folder, but that already works.

Publish can't "zip-it-and-ship-it"

I'm able to successfully "Export" and "Preview" a site as configured, yet when clicking "Publish", after a long pause I'm seeing "Preparing functions..." then after another long pause while npm runs, I'm getting this exception:

Done in 3649ms.
"Elapsed time: 24667.785 msecs"

Preparing functions...
"...AFTER npm install"
[qtp772154516-23] ERROR com.biffweb.impl.middleware - Exception while handling request
java.io.IOException: Cannot run program "zip-it-and-ship-it" (in directory "storage/deploys/4b8f7ba1-cc01-4b87-9a71-23389182e111"): error=2, No such file or directory
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
        at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
        at java.base/java.lang.Runtime.exec(Runtime.java:615)
        at clojure.java.shell$sh.invokeStatic(shell.clj:113)
        at clojure.java.shell$sh.doInvoke(shell.clj:79)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.core$apply.invokeStatic(core.clj:667)
        at clojure.core$apply.invoke(core.clj:662)
        at com.biffweb.impl.util$sh.invokeStatic(util.clj:63)
        at com.biffweb.impl.util$sh.doInvoke(util.clj:62)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.core$apply.invokeStatic(core.clj:667)
        at clojure.core$apply.invoke(core.clj:662)
        at com.biffweb$sh.invokeStatic(biffweb.clj:61)
        at com.biffweb$sh.doInvoke(biffweb.clj:56)
        at clojure.lang.RestFn.invoke(RestFn.java:482)
        at com.platypub.netlify$deploy_BANG_.invokeStatic(netlify.clj:15)
        at com.platypub.netlify$deploy_BANG_.invoke(netlify.clj:10)
        at com.platypub.feat.sites$publish.invokeStatic(sites.clj:156)
        at com.platypub.feat.sites$publish.invoke(sites.clj:152)
        at com.platypub.util$wrap_signed_in$fn__35716.invoke(util.clj:96)

Generate a default meta image for posts in default theme

The default theme already adds a /.../card/ endpoint which you can use to manually create an image (preview or publish, add /card/ to a post's URL, screenshot the node, go back and edit the post, upload the screenshot). It would be much, much nicer if that whole process was done for you, i.e. if you haven't set an image on the post, the default theme generates the image for you and includes it in the post's meta tags.

Show stats for previous newsletter sends

Currently Platypub does not record any information when you send a newsletter. It'd be nice to show, somewhere (for now, perhaps add a link next to "subscribers" on the newsletter tab), a list of the previous posts you've sent out to your newsletter(s), along with the standard metrics like open rate and click-through rate (this would require that open and click tracking have been enabled in mailgun--I've done this for my own domain but I don't think I've mentioned anything about it in platypub's docs yet. There's a toggle for it in mailgun, and I think you have to set up some additional DNS records).

We might not even need to add anything to platypub's DB. e.g. with mailgun's api, can we get a list of the emails that have been sent to a newsletter's address? And use the subject line to infer which post it was for? And then get open rate + click through rate for that send? If so, how long can we get that info from mailgun? Maybe we need to store it in platypub's db anyway for longevity.

Do something to enforce/encourage consistent code formatting

So after writing clojure full-time and solo for the past 3.5 years, this will actually be the first project I've worked on with other people :). I've been using vim's defaults with a couple minor tweaks, however I'm not sure if all of vim's choices are mainstream? (e.g. 2-space argument indentation for function calls).

At a minimum perhaps it'd be helpful to have a style document, and whenever formatting differences come up in PRs, decide on a style and then mention it in the document? Perhaps include editor configurations? Or should we just add a command to the task script that formats the code with cljfmt and be done with it? Whatever we do, I'm not picky about formatting and am happy to change my editor config to match the mainstream.

For people who haven't been doing all their coding in a cave out in the wilderness, what do the projects you work on usually do?

Add a :list/sites attribute

Pretty much the same as #39 but for newsletters. Once this and #39 are closed, we can deprecate the :site/tag attribute: continue displaying it on the edit site page if it is already set, otherwise hide it.

render-site file not found

Sorry if this is jumping the gun while you're in progress: getting error not finding ./render-site when doing a Preview:

[clojure-agent-send-off-pool-4] INFO com.platypub - Generating CSS...
[clojure-agent-send-off-pool-4] INFO com.platypub - CSS done
[qtp169775100-19] ERROR com.biffweb.impl.middleware - Exception while handling request
clojure.lang.ExceptionInfo: chmod: cannot access './render-site': No such file or directory
 {:exit 1, :out "", :err "chmod: cannot access './render-site': No such file or directory\n"}
        at com.biffweb.impl.util$sh.invokeStatic(util.clj:66)
        at com.biffweb.impl.util$sh.doInvoke(util.clj:62)
        at clojure.lang.RestFn.applyTo(RestFn.java:137)
        at clojure.core$apply.invokeStatic(core.clj:667)
        at clojure.core$apply.invoke(core.clj:662)
        at com.biffweb$sh.invokeStatic(biffweb.clj:61)
        at com.biffweb$sh.doInvoke(biffweb.clj:56)
        at clojure.lang.RestFn.invoke(RestFn.java:436)
        at com.platypub.feat.sites$generate_BANG_.invokeStatic(sites.clj:121)
        at com.platypub.feat.sites$generate_BANG_.invoke(sites.clj:107)
        at com.platypub.feat.sites$preview.invokeStatic(sites.clj:128)
        at com.platypub.feat.sites$preview.invoke(sites.clj:125)

(biff/sh "chmod" "+x" (str (io/file dir "render-site")))

Set min height on TinyMCE

TinyMCE expands to fit the content size, but if you don't have much text yet it'll be really short and look dumb. It'd be nice if we can set a minimum height so it fills the screen height.

image

Make it easier to not expose API keys while pair programming

Maybe add a separate secrets.edn file in addition to config.edn. Maybe read from that file whenever you need to use a secret, so secrets aren't stored in the system map. Then you can both edit config.edn and display the system map's contents without leaking any secrets.

add single user mode

Since at this stage (see the roadmap) Platypub is meant to only be used by a single user (and in most cases will be ran locally rather than deployed on the public internet), let's add a key like :com.platypub/single-user-mode or something, where the value is an email address. If the key is set, then when you go to the landing page, you are auto-signed in to that email address and redirected to the posts page. this will also obviate the need for a less ugly landing page. 🦜🦜πŸͺ¨

Support multiple "item" types, not just posts

Platypub's schema has a :post document baked in. Right now we use that for two different types of documents: posts and pages. Some themes would benefit from additional types of documents, like events. We need to figure out how to handle this without bloating the core schema.

See #41. We could have the custom schema define not only individual attributes, but document types as well. This may require some hammock time.

  • What should be in "core" schema and what should be in theme schema? Currently I think most of the post schema should be moved out of core and into themes. Perhaps all of it can be. However Platypub needs to know how to display items in the UI. For example, post-list-item (https://github.com/jacobobryant/platypub/blob/master/src/com/platypub/feat/posts.clj#L267) needs to know the values of :post/{title,status,published-at,edited-at,tags}. Perhaps we have the theme define how items should be rendered in Platypub's navigation.
  • The core schema will at least need to define which user owns the document. Perhaps we replace the :post/user attribute with an :item/user attribute, and then push everything into the themes' schema.
  • How should Platypub/themes know if a given document has a certain type? We could add a :item/type attribute (:item/types might be better), or say "any document with attributes X, Y and Z is a valid Foo document." Or we could have themes define a predicate/malli spec which is used to filter documents. Then themes can use whatever method they want for defining document types. (That may be tricky though--eventually we want to not trust theme code.)

Make TinyMCE match Platypub's colors in dark mode

TinyMCE's default dark theme is blue, which is simply unacceptable for our purposes:

image

For bonus points, in general it might be nice if we could make tinymce blend in more. Maybe get rid of those rounded corners? I don't feel like making a separate issue for this yet.

Make site rendering faster

This function takes about 10 seconds on my machine:

(defn generate! [{:keys [biff/db path-params params dir] :as req}]

Need to profile first. I'm pretty sure tailwind takes up the most time. Maybe there's some way to cache it. Or pass in an opt so render-site only passes the --minify option to tailwind when you're actually publishing the site.

Theoretically it seems like it would be pretty fast to get all the tokens tailwind might recognize via regex and, and then only generate a new css file if there's actually been a change. Sounds like a pain to implement though, unless there's an easily accessible set of regexes laying around somewhere.

The almost gratuitous npm install probably takes up a couple seconds too.

Support theme development within Platypub

After #57 is complete, the final step is to add a code editor to Platypub so people can tweak/develop themes without leaving the app. Besides being convenient for quick tweaks, it'd be great if this helped people get into clojure/programming in general. i.e. maybe you aren't a programmer, but you've got a blog published with Platypub and you want to make a small change to the way it looks--we want the UX to be nice enough so that you could make the change without too much difficulty (even if it requires some trial and error).

Better image component

Currently we use a text input, and after you save and the page reloads, we show a preview:

image

We already have an endpoint for uploading an image to S3. It's used in the post editor (tinymce). Currently when I want to upload an image for one of the image text fields (both posts and sites have an image key), I go to a post, upload an image, copy the url, and omit actually putting the image in the post.

There might be some drop-in js image component we could use. It would also probably not be too hard to just use a normal file input and submit it with htmx, inserting the image preview to the dom once it finishes uploading.

However I do kind of like having the option to paste in a url, for times when I already have an image hosted somewhere. Maybe there's a js component that handles both urls and uploads. Or we could just use both a native text input and file input together, and try to make it not look too ugly.

Rethink navigation/UI, including mobile

After #39 is closed, add a link below Posts for each site you've created:

[Posts]
β”œβ”€β”€ [My Site]
└── [Another Site]
[Sites]
[Newsletters]

The link could look something like /app?site-id=..., i.e. we just pass in a query param to the posts page and use it to filter the posts shown. (that also reminds me we should fix that /app so it's just /posts or something... should make a separate issue for that)

Don't show confirmation dialog when previewing or sending test email

Since merging #51 I have realized that the "return confirm('Send newsletter')" bit also triggers when you click the preview or test send button. We should only show the confirmation dialog when we hit the actual send button. This might be inconvenient since we use the same form for all three actions.

Bundle css with default theme

Currently the default theme generates css with tailwind whenever you run it. This can take a while if you're running platypub on a tiny vps. Instead we should generate the CSS during development and commit the file to git, and stop calling tailwind at run time. We may need to have render-site copy the css file over to the right location.

Add anchors to headings in default theme posts

e.g. if the post content includes <h2>Foo bar</h2>, we want to transform it to <h2 id="foo-bar">Foo bar</h2>. Maybe even add one of those fancy copy-to-clipboard icons that appear on hover, like GitHub does:

image

markdown-to-html libraries often have a feature for this, but since we start with html, we'll need an html parser. In Clojure it would be pretty easy to use hickory + postwalk to replace any h1-6 nodes. However with babashka looks like we'll need to use pods? I've never used pods myself yet.

Auto generate Biff secrets + save them to config.edn?

:biff/jwt-secret and :biff.middleware/cookie-secret are nil by default in config.edn.TEMPLATE. Normally when you create a new Biff project, the project creation script generates some random secrets for you. But when cloning an existing Biff project (like Platypub) that doesn't happen. So I think whenever people start up the app, they're getting a new random set of secrets? Which would mean they have to sign in every time. (I have secrets myself since I'm the one who generated the Platypub project!)

We should add instructions for generating secrets and add them to the readme. Maybe even add a command to do it all automatically if it's not too much work.

Make title field more prominent

Right now the title field is off to the side with the rest of the metadata. I think it'd look nicer and feel less weird if it were placed above the editor, with enlarged font and stuff.

image

Some editors like Substack's blend the title field into the editor. That sounds like way too much work for our situation imo. I'd rather leave the editor as a mostly drop-in component and just stick a regular text input above it.

Rethink the theme package system

After #56 (and probably also #21) are complete, we should think about what the best way to publish/share/install themes would be. Right now the :site/theme field is a string which refers to a directory under themes/, e.g. default -> themes/default/. It would probably be better if it was a URL to a git repository. Maybe include a hash too, or just have platypub check for new versions periodically. Whenever you preview or deploy a site, Platypub would check if the repo has been downloaded already and clone it if not.

Maybe we could even have a directory + search for themes within platypub? e.g. if you tag your github repository with platypub, then it'll show up in the directory. and there's nice UI for installing/selecting themes so it'll feel natural for non-technical people.

Resize images on upload/on render

It'd be nice if we could handle image resizing in one way or another. #17 talks about resizing the image element in the DOM but doesn't cover resizing the original file. (Same for the default theme code; images are displayed at the right size, but the files will sometimes be bigger than they need to be.)

One option: have theme code use https://images.weserv.nl/, a free image resize/editing service. It's very convenient; you pass in a url to the original file along with some size params etc and they'll resize, cache, and serve the image for you on demand.

Another option: upload-image could put the original + a few standard sizes on s3, and then we update the data model in one way or another to include all the sizes. Perhaps add keys like :image/url-small, :image/url-medium etc. Then in different contexts we use different urls. Maybe when you're uploading an image from the TinyMCE, we use a medium/large size ("large" might still be smaller than the original size), and when you're uploading an image in the post sidebar (i.e. for use in social media previews) then we use a smaller size. Or have theme code figure out which size to use somehow.

I like the first option, but one downside is you can't use it for the post metadata because images.weserv.nl's robots.txt file. otoh often for preview images they're custom made in the correct size to begin with so maybe not a big deal; just use the original url for that and use images.weserv.nl for images in post content etc. πŸ€·β€β™‚οΈ

After a test email is sent, preserve the newsletter choice

e.g. if you have two newsletters, and you select the second one in the dropdown on the send page, then after you send a test email, the second one should still be selected. Currently it goes back to the first one, which sooner or later is going to cause me to make an embarrassing mistake.

Add file extensions to render-site and render-email scripts for IDE support?

In Calva the breadcrumbs at the top of these scripts (supplied via clojure-lsp) are missing, making it more difficult to navigate the functions. I opened an issue in Calva which points up a client-server disconnect between Calva and clojure-lsp when there is no file extension. Relying on the shebang: "Yeah, adding to much complexity for a very rare use-case doesn’t sound like a good idea."

The lack of file extension makes it easy to switch a script to a bash implementation, I guess.

Make slug inferring work again

I just remembered that when I overhauled the data model I never got around to making #26 still work. It's more difficult now since everything related to posts must be done generically. I did include something in the config for this, but platypub doesn't actually do anything with that yet. I also am not really sure how exactly that should work. probably needs more thinking.

Add subscribers page

Add a page somewhere (? exact location is left as an exercise for whoever does this*) so you can see your list of subscribers for a given newsletter in a table, including metadata stored in mailgun (e.g. the datetime at which they subscribed). sort them so new subscribers are shown at the top. Maybe even include a little chart.

* or just put it somewhere really obnoxious and then someone else (like me...) will end up moving it to a better spot

Use select component for theme

sites and lists both have a theme field:
image

Instead of a text field, this just be a select field (use this) that is populated with the children of the themes/ directory.

Better tags component

image

Replace that with Tagify. We're using it in The Sample:

image

(Tags component is used for lists and posts. Not used for sites, which support only a single tag--might change that later.)

Show helpful error messages if you're missing config

Right now if you haven't added a netlify api key and you try to create a site, you'll get an ugly 500 error page. Better if we showed a page that said "you need to add a netlify api key before you create a site."

Also check what happens if other api keys are omitted, and add similar error pages where appropriate.

Use pills instead of dropdown menu for mobile navigation

Pills are nice cause you don't have to do an extra tap to make them appear. And if the user is on a tiny screen, they'll wrap. And no need for custom js/hyperscript. Here's some code I just copied from The Sample (need to at least change bg-dark to something else):

image

(defn pills [{:keys [options active]}]
  [:.flex.mx-3.sm:mx-0.overflow-x-auto.whitespace-nowrap
   (for [{:keys [value label href]} options]
     [:a.mr-1.p-2
      {:class (if (= active value)
                "bg-dark rounded text-white"
                "link")
       :href href}
      label])])

tailwindcss command cannot find module when previewing/publishing

From Slack:

INFO com.platypub.feat.sites - node:internal/modules/cjs/loader:942
  throw err;
  ^

Error: Cannot find module '../peers/index.js'
Require stack:
- /Users/callumherries/code/clj/play/platypub/storage/previews/6d1724e6-cce0-46ce-95f0-008ca3a11895/node_modules/.bin/tailwindcss
    at Module._resolveFilename (node:internal/modules/cjs/loader:939:15)
    at Module._load (node:internal/modules/cjs/loader:780:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/Users/callumherries/code/clj/play/platypub/storage/previews/6d1724e6-cce0-46ce-95f0-008ca3a11895/node_modules/.bin/tailwindcss:3:16)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Module._load (node:internal/modules/cjs/loader:827:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/callumherries/code/clj/play/platypub/storage/previews/6d1724e6-cce0-46ce-95f0-008ca3a11895/node_modules/.bin/tailwindcss'
  ]
}

Node.js v18.3.0
"Elapsed time: 820.852262 msecs"
$ node -v
v18.3.0
$ npm -v
8.12.1 

https://clojurians.slack.com/archives/C013Y4VG20J/p1655029179669229?thread_ts=1654971210.506299&cid=C013Y4VG20J

Rethink data model + navigation: make it more hierarchical?

There are three main types of documents: sites, lists (newsletters), and posts. Currently Platypub's schema does not model any relationships between these. When a site is rendered, all the documents are passed to the theme code, which is responsible for deciding which posts and lists should be included on the current site. The default theme does this by looking at the :site/tag, :list/tags and :post/tags attributes. e.g. you'd set it to example-site on your site, then you'd add example-site to the list's tags and the posts' tags.

This makes things flexible. You could share a single post between multiple sites, for example. However I'm not really sure if that will ever actually be needed. If we added a :post/site and a :list/site attribute--i.e. make it so every post belongs to a single, specific site, and same for lists--would anything actually be lost?

Regardless, we probably want to restructure the UI so that lists and posts are grouped under a specific site by default. If we decide to continue with the flexible data model, then we can have a way to break out of that UI model.

Maybe we add the :post/site and :list/site attributes and just let it be an optional field. Or allow a special value like :system or :none. Or even just... make a another site for any "orphaned" posts and lists and just don't publish it.

So yeah I think I'm leaning towards making posts and lists be children of sites. If anyone can actually think of any scenarios where you wouldn't want that kind of relationship, please comment.

Sending domain is hard-coded in post/render-email

In the posts/render-email function, the sending domain used in the value for the :from key is currently hard-coded to "[email protected]"

:from (str (:list/title lst) " <[email protected]>")

Replacing the address with the newsletter's :posts/reply-to value is working for me right now.

Do we also need a separate attribute for the sending domain, for cases where the :post/reply-to value should differ from the sending domain?

I don't have much experience with this. The "doreply" account name is interesting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.