Moving from Medium
31st Jan '23 • 4 of your Earth minutesI finally did it! I took the plunge and am running my own blog.
It's been many years since I ran my own site 'properly'. And now that it's practically free, it was about time.
For the eagle-eyed among you, you'll know that I sporadically published content to Medium. But with the sheer volume of content there—plus their approach to paywalling–I've really lost the desire to publish there.
There was a time when the writing experience on Medium truly was delightful, but I think that has disappeared too.
I'm sure it will do well for a while longer, but it's just not for me.
I haven't shut my account there down completely yet, but I'm sure it won't be long before I do.
But I am (at least to some degree) proud of the few things I wrote on there. So I wanted to make sure I kept those articles around.
I also have a lot of very old articles on Blogger that I've never done anything with. I'm sure there's some cringey nonsense in there.
¶What this runs on
I decided back in September '22 to pull all of my Medium content down using their export tool.
My site has been a Statamic-based, statically-generated, Netlify-served thing just for the homepage for almost 3 years, so it was about time I gave it something else to do.
I put all of the files from Medium's download into a folder and wrote a simple command:
1<?php 2 3namespace App\Console\Commands; 4 5use Illuminate\Console\Command; 6use Illuminate\Support\Facades\File; 7use Illuminate\Support\Facades\Storage; 8use Illuminate\Support\Str; 9use League\HTMLToMarkdown\HtmlConverter;10use Statamic\Facades\YAML;11 12class MediumConverter extends Command13{14 /**15 * The name and signature of the console command.16 *17 * @var string18 */19 protected $signature = 'convert:medium';20 21 /**22 * The console command description.23 *24 * @var string25 */26 protected $description = 'Command description';27 28 /**29 * Create a new command instance.30 *31 * @return void32 */33 public function __construct()34 {35 parent::__construct();36 }37 38 /**39 * Execute the console command.40 *41 * @return int42 */43 public function handle()44 {45 $converter = new HtmlConverter(['strip_tags' => true]);46 47 $files = Storage::files('medium-posts');48 49 foreach ($files as $file) {50 // Make the filename Statamic friendly51 $filename = Str::beforeLast(Str::replaceFirst('_', '.', Str::lower(File::name($file))), '-').'.md';52 53 $published = true;54 55 if (Str::startsWith($filename, 'draft')) {56 $published = false;57 58 // Strip 'draft' from the filename59 $filename = Str::replaceFirst('draft', date('Y-m-d'), $filename);60 }61 62 $slug = Str::after($filename, '.');63 64 // Clear out the Medium CSS and meta65 $html = preg_replace('/\<head\>.*\<\/head\>/ims', '', Storage::get($file));66 67 $markdown = $converter->convert($html);68 69 $collection = collect(explode("\n", $markdown));70 71 $title = $collection->shift();72 $id = (string) Str::uuid();73 74 $collection = $collection->skipUntil(function ($item) {75 return Str::endsWith($item, '---');76 });77 78 $subtitle = trim(Str::replace('---', '', $collection->shift()));79 80 // Remove the Medium footer81 $collection->pop(8);82 83 $markdown = $collection->implode("\n");84 85 $frontmatter = YAML::dumpFrontMatter(compact('id', 'title', 'subtitle', 'published'));86 87 File::put(base_path("content/collections/articles/{$filename}"), $frontmatter.$markdown);88 }89 90 return 0;91 }92}
This did enough to create all of the posts in a format that Statamic would be happy with.
I then needed to go through and do a few chunks of manual cleanup (some of which I could have made a part of this command, but 🤷🏻♂️) - this was essentially a bunch of 'find and replace' in my IDE.
I've added a few styles and adjusted things for better reading and that's it. I haven't moved any images anywhere yet.
My cheap and cheerful, self-hosted blog, backed by a fully-fledged CMS and hosted for free.
The best part? I can completely craft the editor experience I want. I write content and save it locally, so I don't need an internet connection just to write. When I'm ready to publish, I just commit and push via Git.
What's more, I can do all of that from the CMS itself thanks to my Statamic Git add-on!
Even better: everyone can read my content without hitting some signup process or banners all over the place.
Beautiful