Coder Social home page Coder Social logo

engil / canopy Goto Github PK

View Code? Open in Web Editor NEW
120.0 19.0 27.0 1004 KB

A git-blogging unikernel written using MirageOS

License: ISC License

OCaml 85.71% JavaScript 0.40% Shell 1.93% Dockerfile 2.50% Less 9.46%
ocaml mirage mirageos irmin unikernel blog-engine

canopy's Introduction

Canopy - A git-blogging unikernel 🌿 Build Status

Canopy is an attempt at writting a blog-engine based on Git using MirageOS.

The goal is to provide a simple blog platform that only requires you to provide a Git remote URL and respecting some architecture rules within the said repository.

Canopy is written in OCaml using MirageOS and Irmin. It is running on both Unix and Xen.

HTTPS/TLS support

Canopy has TLS support, you have to first create your TLS private key and get a signed certificate (using certify and/or let's encrypt - sorry, no let's encrypt client in OCaml yet).

Put your unencrypted private key into tls/server.key, and your full certificate chain (starting with the server certificate, then the intermediate CAs, no need to include the root CA) into tls/server.pem before running mirage configure (which will embed them as OCaml code into the binary).

You can configure Canopy with --tls=<port> to run it as HTTPS service. Canopy will then respond to HTTP requests with a moved permanently redirection to the HTTPS URL. Also, the HTTPS service includes a strict transport security HTTP header (containing max-age=31536000).

Compiling and running Canopy

You will need at least OCaml 4.07.1, opam 2.0 and mirage 3.7.5 before starting. To setup a mirage environment, please refer to the mirage website.

Checkout Canopy repository, then go inside:

# Configure the mirage application, compile assets
mirage configure -t unix
# Get dependencies
make depend
# Compile Canopy
make
# Run it
./canopy

Note: if you run Canopy with a grsec kernel you might have to relax memory-mapping restrictions (i.e.: paxctl -cm canopy) and load the tun module.

A server will be launched using the specified URL as the git remote, Index as the default page rendered on the blog (it must exist within the repository) and 8080 is the listening port. You can see more options by running ./canopy --help.

To prepare your own data repository, you have to use npm, less-css and browserify if you want to compile and retrieve everything related to the blog-styling. The mirage configure step takes care of fetching and recompiling all assets. If none of the mentioned programs were to be found, the configure step will use the tarball found in the assets directory, containing already compiled assets.

# OR start with git clone git://github.com/Engil/__blog.git ;)
mkdir canopy-data
cd canopy-data
git init .
# Populate data using npm, browserify, etc.
if [ -x `which npm` ] ; then
  ./populate.sh /tmp/data
else
  # OR use pregenerated tarball
  cd /tmp/data && tar xf assets/assets_generated.tar.gz
  cd /tmp/data && mv disk/static .
fi;

git add static

# Generate a UUID for the Atom feed
uuidtrip -r > .config/uuid
# Add blog name (defaults to "Canopy")
echo "My blog" > .config/blog_name
git add .config

git commit -m initial

# configure git remote and push
git remote add origin [email protected]/me/__blog.git
git push origin master

You can run Canopy with your own data repository:

./canopy -r git://github.com/me/__blog.git

You can use git branches for drafting changes: ./canopy -r git://github.com/me/__blog.git#dev.

Compiling and running on Xen

If you want to build for xen, there's a couple of packages that need to be installed from specific branches.

opam pin add dolog 'https://github.com/UnixJunkie/dolog.git#no_unix'
opam pin add bin_prot 'https://github.com/hannesm/bin_prot.git#113.33.00+xen'

You can either build with support for DHCP or static ip, just specifying it as command line arguments, for instance:

mirage configure --xen --dhcp false --net direct --ip 10.0.0.2 --netmask 255.255.255.0 --gateways 10.0.0.1
make

Make sure to have br0 set up for this. For example, I did:

# provide ip forwarding
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
# create a new bridge
brctl addbr br0
ip addr dev br0 add 10.0.0.1/24
ip link set br0 up

Finally you can run your unikernel!

xl create -c canopy.xl

Git push hooks

To keep your Canopy content updated, you need to tell your instance that new content is available on the git remote, then it will just pull the changes and will serve the new content.

To do that, Canopy use a simple URL path that you can set into Canopy_config.ml (hook_push_path).

Using Github, setting up this hook is pretty simple: just add a push webhook targeting your URL + your hook path. For example, by default this hook path is push, so the resulting URL is http://yourdomain/push.

If you are not using Github, you can just find a way (post-commit-hooks, for example) to run a HTTP request to this URL.

How Canopy works

Canopy will require you to provide a Git remote uri. Once started, it will clone in-memory the repository content and serve the content in a more or less organized way.

Each file at the root of the repository is considered a standalone page, more like the usual « About » or « Contact » pages. They will have their own entries in the navigation menu.

Each directories will contains more pages, but that will be classified under a category decided by the name of the said directory. For example, a posts/hello-word.md file will be a new blog post under the Posts category. You can use it to emulate some sort of tag, like for example having an OCaml directory regrouping all you writing in everyone's favorite language. :-)

Static assets (not processed) can be added into "static" subdir, configuration values below ".config".

The file syntax of articles is just plain markdown, everything should be supported out-the-box (depending on the ocaml-omd markdown implementation), with a little bit of extra informations absolutely needed at the top of each files.

---
title: A blog entry
author: Me
author_url: http://www.an_optional_link_that_wraps_the_author.com
abstract: A simple line telling what this article is all about, will be displayed in listing pages. (optional)
---
article content

If you don't respect this syntax, then the article won't show up in the resulting website.

You can also put some MathJax inside articles, Mathjax is activated if you pass the --mathjax parameter at startup.

canopy's People

Contributors

abbysmal avatar andrebauer avatar armael avatar avsm avatar dinosaure avatar gasche avatar gjaldon avatar hannesm avatar mmaker avatar olleolleolle avatar reynir avatar ricoantoniofelix avatar samoht avatar voila avatar wallymathieu 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

canopy's Issues

updates to navbar should invalidate all the timestamps

(carried over from #55):
The timestamp is correct on __blog after updating an article + push, however we still didn't fixed the fact that if a page was cached (relying on it's timestamp), and if you add a page that will show up in the navbar (so, if you add an article at the root of the repo), once you go back to this cached page after the update, the navbar isn't updated (since the cached page rely on the article individual timestamp).

sorry I didn't keep that in my mind while doing any timestamp work @Engil... needs for sure some rethinking of the last_updated dependencies... basically addition/removal of files (or rather directories) should lead to trashing the cache/last-updated...

local font resource

it would be great if Canopy would distribute the font itself, instead of relying onto some remote resource (fonts.googleapis.com)

Moving from Hashtable to Map.Make

As discussed in #30, it would be nice to move to Map.Make instead of using Hashtable.
I don't seed any major problem in doing so, I will do either today or tomorrow.

I think it should be pretty straightforward, the main problem being that we used a single hashtable before and we'll probably need to insert a reference instead… If you have better solutions, feedbacks welcome as usual. :)

feature request: redirect

sometimes I'd like to preserve links (e.g. to /Posts/About, but move the actual page to a different path /About). It would be nice - since we're now supporting more than Markdown files, to support a redirect: /About (seems to be yaml syntax which we agree on atm), which will lead to a 301 Moved Permanently HTTP response.

does this sound like a good idea?

Tags for posts

Having tags in posts would be nice.
A simple implementation would be adding the tags: meta inside the post headers, but maybe something a little bit clever can be figured out using Irmin.

exception in accept

just got this...

Repository pulled
(closed connection 434)
Fatal error: exception Unix.Unix_error(Unix.ECONNABORTED, "accept", "")
Called from file "src/unix/lwt_unix.ml", line 487, characters 13-24

Mime type handling

Currently, Canopy don't send any mime-type informations, would be nice to have it somehow.

feature request: recent activity

there should be an atom feed (and/or html page) describing recent activity. data can be harvested via the commits (just needs some article option -> article option -> html/atom function afaics)

help is welcome (I won't have time to do that)

adding font to disk leads to crash on Xen

so if I embed the font into the disk/static, it dies on xen while trying to serve the first request... i guess there was some in mirage a similar issue, but have trouble finding it... not sure what to do exactly, but after all we should keep the size of the (JS/CSS/font) resources low...

I might investigate further at a future point again if nobody else jumps into that (maybe @samoht @djs55 remeber details about crunch(ing) with lots of data)

serving canopy blogs from a local git repository

I would like to test a local git repository for Canopy blog posts before pushing it to the actual repo. I built Canopy locally, but then I have not manage to get it to read posts from a local git repository.

$ ./mir-canopy -r /home/gasche/Scolaire/neu/icfp-sv/icfp2016-blog/ -i Welcome -p 8080 -u 12345
Manager: connect
Manager: configuring
2016-10-14 20:45.10: INF [git.memory] Reading HEAD
Pulling repository
Fail pull (Failure "Unknown Git protocol")
2016-10-14 20:45.10: INF [git.memory] Reading HEAD
2016-10-14 20:45.10: INF [git.memory] Reading refs/heads/master
2016-10-14 20:45.10: INF [git.memory] Reading HEAD
2016-10-14 20:45.10: INF [git.memory] Reading HEAD
2016-10-14 20:45.10: INF [git.memory] Reading refs/heads/master
HTTP server listening on port 8080
$ ./mir-canopy -r file:///home/gasche/Scolaire/neu/icfp-sv/icfp2016-blog/ -i Welcome -p 8080 -u 12345
Manager: connect
Manager: configuring
2016-10-14 20:44.41: INF [git.memory] Reading HEAD
Pulling repository
Fail pull (Failure "file is not a supported Git protocol")
2016-10-14 20:44.41: INF [git.memory] Reading HEAD
2016-10-14 20:44.41: INF [git.memory] Reading refs/heads/master
2016-10-14 20:44.41: INF [git.memory] Reading HEAD
2016-10-14 20:44.41: INF [git.memory] Reading HEAD
2016-10-14 20:44.41: INF [git.memory] Reading refs/heads/master
HTTP server listening on port 8080

Could this be supported? I grepped for not a supported protocol in the sources but couldn't find any hit for this error message. Which piece of the ecosystem is it that fails to support file?

Also, why does Canopy still run a server and loops infinitely when it failed to resolve the Git repository? Is there anything useful in that, or could it just not quit on this error?

memory leak

(yes, I guess this is the wrong repository, but this is my current testcase) @avsm @samoht

when I used canopy on Unix with the socket stack, it has a constant memory behaviour (printing the live words in 3 places: before a request comes in, after a request is handled, and whenever a connection closes, code is here, doing a full major collection before printing).

using the direct stack, I get (on Xen):

819143 before handling connection live words
819339 after connection live words
819420 conn closed, live words: 
819726 before handling connection live words
819922 after connection live words
820003 conn closed, live words: 

which means ~600 more live words for each TCP connection (this uses wget on the client side) -- on Unix with a tap device, I see a similar behaviour (strongly monotonic increase of live words between closes):

1062215 before handling connection live words
1062249 after connection live words
1062193 conn closed, live words: 
1062750 before handling connection live words
1062784 after connection live words
1062728 conn closed, live words: 

any clue / idea / guess where to look for this? I use mirage-2.8, tcpip-2.8, conduit-0.11.0, mirage-conduit-2.2.0, cohttp-0.20.2, mirage-http-2.5.1, mirage-net-unix-2.2.2, mirage-net-xen-1.4.1....

it is unlikely to be in any unix/xen specific package (since I see similar things with both), maybe conduit/mirage-conduit/tcpip? anyone else sees similar behaviour? (maybe mirage-www? does it auto-restart due to memory issues? does its memory usage increase?)

Improving error reporting in Canopy

Hello,

Following the mailing list report, I was thinking about how we could improve error reporting in Canopy when it tries to pull new content but fails to do so (with, for example, an invalid Canopy file that will be dropped).

Solution I thought about:

  • Storing the failing file and displaying it on the site too (or displaying it only with a specific get parameter ?), with the error written in the page's body ?
  • Having an offline command line utility to check if a file is good ?
  • Having a page displaying git pull's logs and errors ? Page that could be hidden (by using somehow the secret webhook URL ? Or a specific param ?)

What do you think about those ideas ? Any better one in mind ?

feed issues

via (so that we do not forget), esp buenzli's comment here to use this scheme.

current issues from w3 feed validator:

    line 1, column 100: id must be a full and valid URL: full%20stack%20engineer [help]
        ...  rel="self"/><id>full%20stack%20engineer</id><title type="text">full sta ...
                                                     ^
    line 47, column 10: scheme must be a full and valid URL: /tags/security (13 occurrences) [help]
        </content><category scheme="/tags/security" term="security"/><category schem ...
                  ^
    line 47, column 159: id is not a valid TAG: tag:,2016-5-3:Posts/BadRecordMac/1462282097 (5 occurrences) [help]
        ... :,2016-5-3:Posts/BadRecordMac/1462282097</id><title type="text">Catch th ...
                                                     ^

In addition, interoperability with the widest range of feed readers could be improved by implementing the following recommendations.
    line 1, column 73: Relative href value on self link: /atom [help]
        <feed xmlns="http://www.w3.org/2005/Atom"><link href="/atom" rel="self"/><id ...
                                                                                 ^
    line 491, column 314: Two entries with the same value for atom:updated: 2016-04-24T22:01:50-00:00 [help]
        ... title><updated>2016-04-24T22:01:50-00:00</updated><author><name>hannes</ ...

Got HTTPS?

It happens that there's somebody implementing the ACME protocol in pure ocaml.
It would be fantastic if we manage to integrate it in Canopy.

With this issue, I would like to open a discussion on the topic.
For what I can see, we need to converge on:

  • finding a way to serve a file on a custom path. Right now I deal with this part with
    https://github.com/mmaker/ocaml-acme/blob/master/src/acme_client.ml#L38-41
    and expecting a stat server to be running in parallel, serving that directory.
    This is super easy to do with nginx or apache, but how about canopy?
  • launching a Lwt thread, and scheduling future executions of this same command (to renew the certificate)

Prettier printing of the HTML header

Hi there,

I'm now officially a Canopy user thanks to the ICFP'16 blog, and I find it very cool, thanks!

Almost the first thing I did is to look at the HTML source to check that there was a syndication feed available. Unfortunately the (beginning of the) HTML output looks like this:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>ICFP 2016 Liveblog Index</title><meta charset="UTF-8"/><link rel="stylesheet" href="/static/css/bootstrap.min.css"/><link rel="stylesheet" href="/static/css/style.css"/><link rel="stylesheet" href="/static/css/highlight.css"/><script src="/static/js/canopy.js"></script><link rel="alternate" href="/atom" title="ICFP 2016 Liveblog Index" type="application/atom+xml"/></head><body><nav class="navbar navbar-default"><div class="container"><div class="navbar-header"><button class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="/Index">ICFP16</a></div><div class="collapse navbar-collapse collapse"><ul class="nav navbar-nav navbar-right"><li><a href="/CUFP"><span>CUFP</span></a></li><li><a href="/Erlang"><span>Erlang</span></a></li><li><a href="/FARM"><span>FARM</span></a></li><li><a href="/FHPC"><span>FHPC</span></a></li><li><a href="/HIW"><span>HIW</span></a></li><li><a href="/HOPE"><span>HOPE</span></a></li><li><a href="/Haskell"><span>Haskell</span></a></li><li><a href="/ICFP"><span>ICFP</span></a></li><li><a href="/Index"><span>Index</span></a></li><li><a href="/ML"><span>ML</span></a></li><li><a href="/OCaml"><span>OCaml</span></a></li><li><a href="/PLMW"><span>PLMW</span></a></li><li><a href="/Scheme"><span>Scheme</span></a></li><li><a href="/TyDe"><span>TyDe</span></a></li></ul></div></div></nav><main><div class="flex-container"><div class="post"><h2>ICFP 2016 Liveblog Index</h2><span class="author">Written by Gemma Gordon, Anil Madhavapeddy, Gabriel Scherer</span><br/><div></div><span class="date">Published: 2016-09-17 (last updated: 2016-10-12)</span><br/><article>

<p>Welcome to the unofficial <a href='http://conf.researchr.org/home/icfp-2016'>ICFP 2016</a>
liveblog!  This is a resource intended to capture the live notes of activity
across the <a href='http://conf.researchr.org/program/icfp-2016/program-icfp-2016'>hundreds of talks</a> that will be given at ICFP 2016 in Nara, Japan.
Any attendee of the conference is welcome to contribute their notes here, and
we will aggregate them after the event into an archive.</p>

As you can see, the newlines are kept in the content, which ends up nicely spaced out and readable, but the header is all on a single line, which makes it difficult to check that there is indeed an Atom feed present.

I think this is not a theoretical issue: some syndication readers just take the blog URL and find the syndication feed themselves, but some users still go find the feed adress by themselves. Would it be possible to pretty-print the header HTML to make the code easier to read?

I checked the source code, of course, and I see a Tyxml.Html.pp call for the whole document, which does not seem to have any obvious "pretty-print" parameter to toggle (cc @Drup?). I don't know of any easy way to fix it, and it may require new features in Ocsigen upstream (or at least the re-implementation of a Tyxml printer inside Canopy), so I understand that it may not end up being fixed in the end.

In that case, I have a workaround suggestion: the index page of the Canopy blog should have a visible link to the syndication feed, either in written text ("syndication feed (Atom)") or as a feed icon, so that people can get the feed URL by copying the link.

feed icon

Fixing the JS/CSS situation

At the moment, the CSS/JS situation is kind of bad.
We got a few CSS files and JS files we need to retrieve via Bower (which isn't good), and load them somehow in the templates.
@wiredsister did already a great job (thank you!) at cleaning the Less files and making them easier to work on, but here is a list of the thing missing I think I'll be working on next, following @wiredsister suggestions:

  • Use browserify to bundle each JS libraries into one: simpler loading, simpler embedding is needed
  • Try to get rid of style.sh and use config.ml to handle that: on the #mirage IRC, drup suggested to write a custom device to allow running arbitrary shell commands within config.ml. I can't find any example of such a thing and I'm not sure this is actually better than the current situation
  • Get rid of bower: Remove it and use npm and browserify to handle JS libraries, halfway done somewhere in one of my local branches
  • Allow simple template customization through Less files: by using some variable, allowing users to tweak a little bit of their canopy instance look: nothing fancy, but things like colors would a least be nice. That's what I was targeting at first when writing it, but I have a few ideas on how to do it so I'll be working on it one day.
  • Embed JS and CSS file into the repository (?): I'm not sure on how to this, but the main rationale being it would be avoiding the npm and less dependencies if the user don't want to tweak the interface.

I think I covered most of the things related to CSS/JS, if you have suggestions on how to properly do most of those things, those are welcome. :)
(also ping @hannesm, @dinosaure)

add config to data repository

there are too many command-line arguments already, thus (also via this issue) we should have some setup in the data repository with those elements we don't need for startup:

  • title
  • index page
  • domain name
  • uuid for feed (or seed for uuid)

Todolist for the first Canopy release

This issue will be about discussing the feature set expected for a first release of Canopy.

Features discussed

  • Tags (header now supports the tags field, each tags separated by a ,)
  • Sorting listing by date
  • Multiple content type: see commit 07403c8
  • Better error reporting: When a file can't be correctly parsed, respond to the hook http request something useful.
  • Running on Xen
  • Getting a release for pinned dependencies

I think I didn't forgot anything. If more features are needed, this is the right issue to discuss about them. :) (@avsm)

For the « Running on Xen » bit, @mmaker made sure it worked during the hackathon but i'm not too sure about the current status. Needs to try it again.

Also, before the release, it would be nice to have a release for some of the dependencies Canopy needs to pin in order to work.
The main culprit are currently:

Pinging @samoht and @yomimono :-)

About the content type feature, the only thing needed is to find use cases for more of them. I am working on a irclog content type in order to display nicely the logs from the bi-monthly things discussed yesterday, as a first try.

I think everything is here, so feel free to discuss, and thanks to all of you for your feedbacks and your help during the development of Canopy! 💯

Unable to build Canopy in Macos

Since I couldn't build Canopy on my Archlinux, I tried it on my Macos. Unfortunately, it doesn't build on it too. After upgrading Mirage to 3.0, I ran the ff commands:

$ opam pin add tyxml --dev
$ mirage configure
$ make depend
$ make

Running make gives me the ff error:

File "static1.mli", line 5, characters 8-16:
Error: Unbound module V1
Command exited with code 2.
run ['ocamlbuild' '-use-ocamlfind' '-classic-display' '-tags'
     'predicate(mirage_unix),warn(A-4-41-42-44),debug,bin_annot,strict_sequence,principal,safe_string,thread,color(always)'
     '-pkgs'
     'cohttp,conduit,conduit.mirage,decompress,functoria-runtime,io-page,io-page.unix,irmin,irmin-mirage,logs,lwt,magic-mime,mirage-clock,mirage-clock-unix,mirage-flow,mirage-flow-lwt,mirage-http,mirage-kv-lwt,mirage-logs,mirage-runtime,mirage-types,mirage-types-lwt,mirage-unix,nocrypto,nocrypto.lwt,omd,ptime,re,syndic,tcpip,tcpip.stack-socket,tcpip.tcpv4-socket,tcpip.udpv4-socket,tls,tls.mirage,tyxml,uuidm'
     '-cflags' '-g' '-lflags' '-g' '-tag-line' '<static*.*>: warn(-32-34)'
     '-X' '_build-ukvm' 'main.native']: exited with 10
make: *** [build] Error 1

Is this a bug or was I supposed to do some additional config?

HTTP last modified header

would be great if Canopy would emit Last-Modified headers (and respect If-Modified-Since), thus subsequent requests would not need to fetch all dependent resources (CSS/JS/..). For static pages, this could be the startup time of Canopy, for articles there is already a last_updated field :)

fetch from a specific git branch

My understanding is that the blog content is a git directory that can be manipulated using the usual git tools. In particular, a natural workflow for me is to fork an existing blog (a git repository), and prepare a pull request to propose a change by creating a fresh branch and doing a few commits in that. Before sending the PR, I want to check the result to tell if it renders as I expect.

However, it does not seem to be possible at the moment to specify a branch to use on the remote to fetch content. I tried -r URL#branch, or -r URL:branch, and neither work.

$ ./mir-canopy -r https://github.com/gasche/icfp2016-blog#student-volunteer-blog-posts -i Welcome -p 8080 -u 12345
Manager: connect
Manager: configuring
2016-10-15 01:58.13: INF [git.memory] Reading HEAD
Pulling repository
2016-10-15 01:58.14: ERR [git.http] with_http: 404 Not Found
Raised at file "pervasives.ml", line 32, characters 22-33
Called from file "src/core/lwt.ml", line 653, characters 66-69
2016-10-15 01:58.14: ERR [git.mirage] Git_mirage.IO.read_exactly: expecting 4, got 0
Fail pull (Failure "Git_mirage.IO.read_exactly: expecting 4, got 0")
2016-10-15 01:58.14: INF [git.memory] Reading HEAD
2016-10-15 01:58.14: INF [git.memory] Reading refs/heads/master
2016-10-15 01:58.14: INF [git.memory] Reading HEAD
2016-10-15 01:58.14: INF [git.memory] Reading HEAD
2016-10-15 01:58.14: INF [git.memory] Reading refs/heads/master
HTTP server listening on port 8080

Master doesn't build

Error: This expression has type Ptime.t
       but an expression was expected of type
         Syndic.Atom.published = CalendarLib.Calendar.t

Do I need to pin something perhaps?

published timestamp

would be great to have an "initally published" timestamp, along the last modified one (hopefully this information can be retrieved via git)

title of index page

I set my index to Posts (-i Posts), which results in the page title Listing... where I'd prefer the blog name..

Unable to run on latest master

I tried running latest master of Canopy on my new Arch Linux install but get the ff error when trying to run ./main.native:

2017-03-06 20:09:04 +08:00: INF [tcpip-stack-socket] Manager: connect
2017-03-06 20:09:04 +08:00: INF [tcpip-stack-socket] Manager: configuring
2017-03-06 20:09:04 +08:00: INF [canopy-store] pulling repository
2017-03-06 20:09:09 +08:00: INF [git.sync] remote: Counting objects: 100, done.

2017-03-06 20:09:11 +08:00: INF [git.sync] remote: Total 100 (delta 0), reused 0 (delta 0), pack-reused 100

2017-03-06 20:09:11 +08:00: INF [git.sync] Received a pack file of 341174 bytes.
Parse error: invalid: 5 is reserved
2017-03-06 20:09:11 +08:00: WRN [canopy-store] failed pull Mstruct.Parse_error("invalid: 5 is reserved")
2017-03-06 20:09:11 +08:00: ERR [application] main: (Invalid_argument ".config/uuid is required in the remote git repository")
Raised at file "pervasives.ml", line 33, characters 20-45
Called from file "src/core/lwt.ml", line 684, characters 36-41

I checked the default engil/__blog repo and it has the .config/uuid file that it is looking for. Any idea what may have caused this? Is there additional setup I should beyond the following?

$ mirage configure
$ make depend
$ make

feature request: Support of author URL

The author: frontmatter metadata can contain rich text in the form of Markdown.

It would be cool if that were rendered.

The author information on some of the articles here could look cooler with Markdown:
http://canopy.mirage.io/tags/help%20needed

Update: Changed the feature request to be about adding a author_url optional metadata field, which (if present) would render a hyperlink around the author name.

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.