I've made an alternative frontend to Medium:

If you, like me, are occasionally forced to read articles on, now you can read them on Scribe instead! Feedback welcome.

@edwardloveall Thank you for this, now we just need a browser extension that does this automatically :D


Yep that worked beautifully, here's for someone who wants to setup it similarly

@huntra Nice! I'll add instructions like this to the homepage eventually. Here's how to do it in one redirect instead of two:

@edwardloveall @huntra Awesome! Thanks for letting me know about that. I've been using Privacy Redirect on Brave but now I should be able to automatically redirect Reddit links to Reveddit in order to view censored content.


Great idea!

Question: how does it handle the username as URLs?

@RussSharek Scribe doesn’t handle subdomains exactly, but it only needs the post id at the end of the url. Here’s a redirect you could set up that would work with subdomains for example

@meena do you mean any article displayed via amp? No, it’s only for posts. Unless I’m misunderstanding what you’re asking and medium has some special amp thing? As I genuinely don't know, what's bad about Medium (or their front-end, if it's only that)? I've read one or two things on it before, and not noticed anything.

@robflop It's a good question. Here's a few links I've gathered on the topic: in particular links to a bunch more reasons. I personally don't like anyone trying to take over an open ecosystem and become the dominant player of that ecosystem. I'm also concerned about what data they are gathering on me.

@edwardloveall This is great. Is there a way to handle medium websites under a different domain name, like towards data science?

@huy_ngo i can’t think of a good way to automatically detect and redirect them, but replacing their custom domain with should work the same! All that Scribe needs is the post id at the end

@edwardloveall Hi, had you considered putting an example for that on the homepage?

We assumed that for , it would work like , when in fact it works as you said - just - whether the domain is custom or not.

Since medium likes to promote custom domains as a feature it might be good to have an example up for people that aren't super code-savvy (us lol).

Thanks for making the tool though, just heard about it & glad it exists!

@noyovo Hi! Thanks and sorry I didn't respond. I just added some more instruction on to help people figure this out. I didn't want to pick a particular domain to link to because I felt weird about targeting a particular site. Hopefully it's easier to figure out for everyone now! 😃

@edwardloveall No worries about the response time!

There's now a line on the page that says: "Custom domains work the too. See below for a How-To." Assuming that's just a typo in the first sentence, right?

@noyovo Oof yes. Thanks. I shouldn't code late in the day. I'll try to fix that today.

@kspatlas In all seriousness, I reverse engineered some of their API, then built an app to parse and render it with Crystal (and the Lucky web framework). I can dive deeper if you have a specific question about any of that.

@edwardloveall I just finished setting Scribe up on NixNet :bolbcheer: (haven’t added it to the homepage yet though)

I did run into a couple of issues. On Debian 11, pkgconf is required for building lib_ssl. I’m not sure whether another report needs to be opened in the crystal-lang repo for that or whether it should be mentioned in the Lucky bug tracker; there were a few issues already open in the crystal-lang repo about fixing it with pkg-conf on Arch Linux, but nothing anywhere else mentioning the solution for Debian.

The second snag was with database creation and initialisation. From hosting a lot of other open source web applications, the standard is usually to create the user/db manually then put those details in the config file, so that’s what I assumed was necessary here as well. Instead, a postgres user needs to be created with the CREATEDB permission so lucky db.create can handle that without failing. It might be good to mention that in Scribe’s README.

Next is how Scribe binds to network interfaces. I’m running Scribe inside LXD so it needs to listen on all interfaces for the reverse proxy on the host to successfully connect; I did that by searching for instances of and changing that in config/watch.yml to I’m completely unfamiliar with this whole stack; is there a more “proper” way to do it? :meowSmileSweat:

Fourth is the generated URL on the homepage. At the moment, that’s localhost:5000 but that won’t work unless everyone has an SSH tunnel into my server to proxy the port :blobfoxlaugh: How did you set that for

Last question! What’s the best way to daemonize the whole thing? Right now, I have lucky dev running in tmux, but I would rather let systemd handle it so it starts on boot and restarts if something causes it to crash.

@amolith Wowowow! This is amazing! Thanks for deploying. I'd love for the community to have multiple instances so thanks for just doing this. And >24h after I announced, no less!

Now for your questions:

@amolith I deployed on Ubuntu so I'm not sure about the specifics of open_ssl, crystal, Debian, and lucky. My _guess_ would be it's a crystal thing, but it's hard to say. I'd start there or maybe even in the Crystal discord

@amolith postgres: I absolutely need to do something with the readme. One nice thing about this app is it doesn't actually need postgres. Lucky ships with Avram which wants postgres, but you can set the DATABASE_URL env to literally any properly formatted postgres url. Here's mine: DATABASE_URL=postgres://does@not/mater

@amolith Never used LXD. What I do is run it on localhost:5000 as normal, and then proxy it through nginx. Something like:

upstream scribe {
server localhost:5000 fail_timeout=0;

server {
location @scribe {
proxy_pass http://scribe;

There's more to it than just that but that's the proxying part. I'd be happy to jump on a screen share and show you

@amolith Fourth: I'm pretty sure that's set with the APP_DOMAIN env var:

@amolith Last question: Just like you're thinking, I used a systemd service. Here's the template I use in my Ansible playbook:

@amolith Thanks again for getting this deployed! More than happy to share what I know about it and make better directions for others. Just ping me.

@edwardloveall That example systemd service answered all of my questions! It's up and works exactly as expected now, thank you :)
@edwardloveall @amolith scribe is supported by farside! If you link to e.g.… it redirects to you the post on one of the known and up scribe instances.
@clacke you could also add (URL with embedded HTTP Basic Auth credentials) and to the list if you wanted :flan_guns:

@edwardloveall Awesome, will test it s00n(tm)...
Hopefully it works nicely cus I don't want to make an account on medium just to read articles >.>

@alcinnz I pushed a fix. Can you double check that it works for you?

@edwardloveall Awesome! This looks to be a cool project!

I did run into a bug while testing this, though: using Redirector, Scribe will try to parse Medium websites that have custom domains and fail. An example is this article:

(I'm not sure if this is intended behavior or not, since I assumed the redirect rule wouldn't kick in for the custom Medium websites because of their URLs, but apparently navigating to them still passes through Medium?)

@darylsun ooo that's a weird one. Thank you for finding that! I think I know what's going on here. If you curl the site, the query param on the end returns a temporary redirect and _that_ is going through

It's a weird URL though and I'm not quite sure how to parse it yet. I'll give it some thought.

@edwardloveall You're welcome! Take your time, and thanks for your work on this project! 👍

@edwardloveall Oh wow, so fast! Okay, I've confirmed that Scribe parses the custom URLs now. Thank you very much for your hard work! 👍 👍 👍 👍 👍

@edwardloveall this is great, one suggestion I have is to make the code blocks wrap around so that the page isn't scrollable horizontally.

@Coder Thanks! Do you have an example post with code blocks I can take a look at to test with?

@edwardloveall here's one:
the 4th example (Convert from binary to normal text) has a long string of binary characters, which makes the page scrollable horizontally.

Sign in to participate in the conversation
Mastodon for Tech Folks

This Mastodon instance is for people interested in technology. Discussions aren't limited to technology, because tech folks shouldn't be limited to technology either!