
A minimal blog engine written in Go, compatible with Ghost themes - Maksadbek
https://kabukky.github.io/journey/
======
Kabukks
Author of Journey here (thanks Maksadbek for posting it on HN). I'm going to
repost my comment from Reddit:

I've been working on this blog engine in my spare time for the last few
months. My blog has been running on it without hiccups for about a month now
(low volume, 700 visits a day tops).

I'd like some opinions if anyone has the time to try it out. (Worth pursuing?
Any ideas for features? Should I die in a fire because my code quality sucks?)

Thanks :)

~~~
zura
Regarding Golang's if-hell e.g. in
[https://github.com/kabukky/journey/blob/master/database/upda...](https://github.com/kabukky/journey/blob/master/database/update.go)

Couldn't you use panic/recover locally, inside functions - just for having a
single error handling code?

~~~
vardump
Explicit error recovery is not hell, it's a blessing. Much easier to
understand and to maintain than exception handling.

~~~
tomjakubowski
There is a third way. See Haskell's Either l r, or Rust's Result<T, E> types.
See [http://lucumr.pocoo.org/2014/10/16/on-error-
handling/](http://lucumr.pocoo.org/2014/10/16/on-error-handling/) and
[http://lucumr.pocoo.org/2014/11/6/error-handling-in-
rust/](http://lucumr.pocoo.org/2014/11/6/error-handling-in-rust/)

I don't know why so often, the immediate reaction to legitimate criticism of
this wart in Go is to argue against exceptions, even when nobody has even
brought up exceptions as an alternative.

~~~
vezzy-fnord
Option types are nice. The fourth way (and I think the best) is supervision
trees, though this is more applicable when you have multiple units of
execution... which Go does, so not having something similar out of the box
seems strange.

That said, even something as simple as errors being literal values that you
can pattern match on is surprisingly versatile. Exceptions don't necessarily
have to be awful weights that spill down all over the call stack, either. They
can be distilled to a more basic catch/throw mechanism for shuffling around
error properties and states.

~~~
threeseed
Personally I love option types but working on a large Scala project at the
moment it sometimes results in non ideal behaviour from developers especially
those coming from the Java world.

What I've seen a lot of is swallowing of errors. For example
readFromFile().orElse("") where there is no indication from an outsider that
anything wrong happened. A cool feature would be logging any instance of when
orElse was the result.

Would be curious how these work in other languages.

~~~
Jweb_Guru
The trick is to make it very ergonomic to return the error. I thought Scala
had do notation to make this the case. In Rust, the try! macro (which returns
on error) is shorter than almost any other way to handle an error, so people
usually use that.

------
_mpu
Are people serious when they say they "love the idea" of copying a binary to
their server to run a blog service? It sounds very much like installing a
shareware in the 90s.

In the current context (NSA, generalized spying, ...), I hope that everybody
realizes it's not an ideal way to distribute software.

Please provide cryptographic signatures or at least sha sums, if you really
think this is the best way to distribute software.

~~~
Kabukks
I agree that one shouldn't copy just any binary on their server and run it.
I'd like to help with this. Are you just thinking about providing SHA sums
next to the binaries/zip releases on the download page? What kind of
cryptographic signatures do you have in mind?

Regarding Journey:

You can always compile from source. Go makes that easy, dependencies on GitHub
will be downloaded automatically.

If you trust my builds, the releases page on GitHub is served via HTTPS, so no
one should be tinkering with the binary on the way from the server to you.

~~~
_mpu
In your case, PGP would be the best and not so hard to implement.

If you don't want/know how to use PGP you can also publish the SHA1 sums of
the files available on your download page. It's better than nothing.

The second alternative is weaker because an attacker would simply need to
change the binary and the sum on the website. In the PGP case, the attacker
must get access to your PGP private key, and provided that you use PGP
reasonably (no private key on your web server), this is harder.

------
nodesocket
We run our blog on Ghost ([http://blog.commando.io](http://blog.commando.io)),
and honestly not sure there is much wrong with the node.js implementation. It
can handle insane traffic, gzip, expires headers already supported. You are
correct, it does not support https, but you could either run nginx in front,
or modify the source code a bit.

I do love the idea of just copying a single binary (thanks go) to any server
and running Journey. Is Journey's editing/writing interface up to snuff with
ghost? Support for tags, SEO metadata, full markdown support, image upload?

~~~
Kabukks
There is definitely nothing wrong with Ghost and node.js. I've used it for
some time now and I still love it :)

Two major points drove me while developing Journey: I wanted to learn (more)
about Go (the bigger point here). And I wanted something that I could just
drag and drop on any server to quickly create a temporary blog or micro site
without setting up dependencies like nginx or node.

~~~
nodesocket
Absolutely. I applaud the effort and enthusiasm to learn go. Go is awesome. My
concerns are just feature parity for users wanting a blogging platform to run
in production. You'll need rss feed, sitemaps, tags, SEO metadata, etc.

------
fiatjaf
About theme compatibility between CMSes of all kinds, I wrote a post at
[http://fiatjaf.alhur.es/programming/reusable-pure-css-
themes...](http://fiatjaf.alhur.es/programming/reusable-pure-css-themes/)

And I have a initial implementation of the thing I envisioned at
[http://fiatjaf.alhur.es/classless/showcase/](http://fiatjaf.alhur.es/classless/showcase/)

------
Rapzid
Hi, this is really cool.. I'll admit to having never heard of or used Ghost,
but I applaud the effort of building this to learn a new language. There is
also a hidden value many people underestimate in having a project that is
quite similar to others but in a different language.

I'm really curious about your Lua integration. I had also not previously heard
of gopher-lua. How has your experience with this been?

~~~
Kabukks
Using GopherLua is a pleasant experience. Easily integrated and surprisingly
fast. But the documentation is lacking.

If you use it in a web server that executes Lua with requests, take a look at
the LState pool pattern[1].

[1] [https://github.com/yuin/gopher-lua#the-lstate-pool-
pattern](https://github.com/yuin/gopher-lua#the-lstate-pool-pattern)

------
davis_m
Why would you not name it Goul?

~~~
Kabukks
Oh my god. I'm deeply ashamed now. /thread

------
bootload
Excellent read, going through the source code this afternoon. How did you work
the theme compatibility with Ghost: api?

 __Worth pursuing? __

Yes, can you make money on it? maybe depending on demand. There 's always a
market for well designed tools, especially if you could make it, _' the key
tool'_ to create and prototype themes.

~~~
Kabukks
I pretty much just reverse-engineered the Ghost helpers using the theme
documentation. Take a look at
[https://github.com/kabukky/journey/blob/master/templates/hel...](https://github.com/kabukky/journey/blob/master/templates/helperfunctions.go)
for all helpers that are implemented yet.

I'm not looking to make money off it. It is tempting to expand the
functionality into a full CMS, but that should be a task for a fork.

------
Immortalin
I am really hoping for a good CMS in Go, I am currently using Drupal but the
overhead sometimes is really huge.

------
karmakaze
Source looks well factored to plug in alternate markups. Markdown is great,
but sometimes too limiting.

------
unicornporn
Does it need a database? I see no such information. But, the Github project
says

> high priority goals are support of MySQL, PostgreSQL, and Google App Engine.

~~~
Kabukks
It uses SQLite internally. One Database file at
journey/content/data/journey.db

I'm working on being able to just drag and drop a Ghost db in there and
loading that one. Only the timestamps need to be converted for that to work.

~~~
unicornporn
Cool. Even cooler: it would create static HTML files. I've been searching for
a software like this for long. Jekyll only works on computers I've installed
it on. I want an admin interface, but no db and static output. Only thing I've
found is [http://prose.io](http://prose.io)

------
relaxitup
Looks cool. Tried on Alpine Linux and no worky:

jb:~/web/journey_blog$ sh journey

journey: line 1: ELF4LS�4: not found

journey: line 10: syntax error: unexpected word

and using bash:

jb:~/web/journey_blog$ bash journey

journey: journey: cannot execute binary file

jb:~/web/journey_blog$ ls -ahls journey

11716 -rwxr-xr-x 1 jbrown jbrown 11.4M Apr 28 21:25 journey

~~~
Kabukks
Thanks for trying it! I would guess this is because I build the linux releases
with gnu libc. See here: [http://www.blang.io/2015/04/19/golang-alpine-build-
golang-bi...](http://www.blang.io/2015/04/19/golang-alpine-build-golang-
binaries-for-alpine-linux.html)

You can also try compiling from source (see the Journey Wiki on GitHub for
instructions).

------
srameshc
Something I through I would do to learn Go. Thanks it will be a little easy
learning :)

------
guybrushT
this is very well made. i was hoping to make something like it - but way
(way!) more minimal. here is the first draft -
[http://adombic.appspot.com](http://adombic.appspot.com)

------
Vecrios
Dang, this was next on my side projects ideas. Looks good though.

You looking for contributes?

~~~
Kabukks
Pull requests are very much welcome. :) Here's my high priority feature list
right now:

Gzip support, hashes for serving static assets (and/or expires headers),
multi-user support, support for all of the Ghost theme helpers, MySQL,
Postgres, and Google App Engine support.

------
melted
A template for getting on the front page:

"X that no one uses, now written in Go"

~~~
vitaut
I'd say more: "X that noone uses, now written in language Y that noone uses".

~~~
kid0m4n
Upvoted for inaccuracy!

