factored out most code into lib/