{"id":16704483,"url":"https://github.com/qcam/nabo","last_synced_at":"2025-04-03T02:11:35.767Z","repository":{"id":37405943,"uuid":"92990480","full_name":"qcam/nabo","owner":"qcam","description":"Nabo (納博) - dead simple blog engine","archived":false,"fork":false,"pushed_at":"2021-02-11T14:48:19.000Z","size":206,"stargazers_count":108,"open_issues_count":0,"forks_count":15,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-04-16T10:36:01.386Z","etag":null,"topics":["blog","blog-engine","elixir","elixir-lang"],"latest_commit_sha":null,"homepage":"https://github.com/qcam/nabo","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qcam.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-31T21:31:51.000Z","updated_at":"2024-03-04T02:55:41.000Z","dependencies_parsed_at":"2022-08-18T06:42:50.080Z","dependency_job_id":null,"html_url":"https://github.com/qcam/nabo","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qcam%2Fnabo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qcam%2Fnabo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qcam%2Fnabo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qcam%2Fnabo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qcam","download_url":"https://codeload.github.com/qcam/nabo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246922248,"owners_count":20855345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blog","blog-engine","elixir","elixir-lang"],"created_at":"2024-10-12T19:13:03.306Z","updated_at":"2025-04-03T02:11:35.747Z","avatar_url":"https://github.com/qcam.png","language":"Elixir","readme":"\u003ch1 align=\"center\"\u003e \u003cbr\u003e\u003cimg src=\"logo/nabo.gif?raw=true\" alt=\"nabo\" width=\"350\"\u003e \u003cbr\u003e\n\n# Nabo\n\nDead simple blog engine written in Elixir.\n\nNabo is designed to be a simple, fast, extendable blog engine. You can integrate Nabo to any component\nin your application like Phoenix, Plug.\n\nIt does not include routers or html generators, but focuses on doing one thing and\ndoes it well: manages your blog posts.\n\n## Installation\n\nAdd `:nabo` to your `mix.exs`.\n\nBy default Nabo uses [Jason](https://github.com/michalmuskala/jason/) and\n[Earmark](https://github.com/pragdave/earmark) for its JSON and Markdown\nparsers.\n\n```elixir\ndef deps() do\n  [\n    {:nabo, \"~\u003e 2.0.0\", runtime: false},\n    {:jason, \"~\u003e 1.0.0\", runtime: false}, # optional\n    {:earmark, \"~\u003e 1.4\", runtime: false} # optional\n  ]\nend\n```\n\n## Documentation\n\nFull documentation can be found on [HexDocs](https://hexdocs.pm/nabo/) and you can view an example of how to integrate Nabo to Phoenix [here](https://github.com/qcam/nabo_example).\n\n## Getting started\n\nTo start using Nabo, first you need to create your own repo.\n\nNabo assumes your posts are in `priv/posts`, if they are not, you can change the\n`:root` option in the generated repo.\n\n```elixir\ndefmodule MyWeb.Repo do\n  use Nabo.Repo, root: \"path/to/posts\"\nend\n```\n\nNabo provides `nabo.gen.post` mix task to generate posts.\n\n```\nmix nabo.gen.post my-first-blog-post\n```\n\nAll posts in Nabo should follow this format:\n\n```md\n{\n  \"title\": \"Welcome to Nabo\",\n  \"slug\": \"welcome\",\n  \"published_at\": \"2017-01-01T00:00:00Z\"\n}\n---\nThis is the excerpt of the post in markdown\n---\nThis is the *body* of the post in markdown\n```\n\n### Phoenix integration\n\n```elixir\ndefmodule MyWeb.PostController do\n  use MyWeb.Web, :controller\n\n  def index(conn, _params) do\n    posts = MyWeb.Repo.all()\n    render conn, \"index.html\", posts: posts\n  end\n\n  def show(conn, %{\"id\" =\u003e slug}) do\n    {:ok, post} = MyWeb.Repo.get(slug)\n    #or post = MyWeb.Repo.get!(slug) This will raise if no post was found\n    render conn, \"show.html\", post: post\n  end\nend\n```\n\nThen in your template.\n\n```elixir\n# index.html.eex\n\u003cdiv class=\"posts\"\u003e\n  \u003c%= for post \u003c- @posts do %\u003e\n  \u003cdiv class=\"post\"\u003e\n    \u003ch3\u003e\u003c%= post.title %\u003e\u003c/h3\u003e\n    \u003cdiv class=\"excerpt\"\u003e\u003c%= raw post.excerpt_html %\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  \u003c% end %\u003e\n\u003c/div\u003e\n```\n\n```elixir\n# show.html.eex\n\u003cdiv class=\"post\"\u003e\n  \u003ch1\u003e\u003c%= @post.title %\u003e\u003c/h1\u003e\n  \u003cdiv class=\"body\"\u003e\u003c%= raw @post.body_html %\u003e\u003c/div\u003e\n\u003c/div\u003e\n```\n\n### Plug integration\n\n```elixir\ndefmodule MyWeb.Router do\n  use Plug.Router\n  import Plug.Conn\n\n  plug :match\n  plug :dispatch\n\n  get \"/posts\" do\n    posts = MyWeb.Repo.all()\n\n    body =\n      posts\n      |\u003e Enum.map(\u0026 %{title: \u00261.title, slug: \u00261.slug})\n      |\u003e Poison.encode!\n\n    conn\n    |\u003e put_resp_header(\"content-type\", \"application/json;charset=utf-8\")\n    |\u003e send_resp(200, body)\n    |\u003e halt()\n  end\n\n  get \"/posts/:slug\" do\n    case MyWeb.Repo.get(slug) do\n      {:ok, %Nabo.Post{title: title, body_html: body_html}} -\u003e\n        body = %{title: title, body: body_html} |\u003e Poison.encode!\n        conn\n        |\u003e put_resp_header(\"content-type\", \"application/json;charset=utf-8\")\n        |\u003e send_resp(200, body)\n        |\u003e halt()\n      {:error, reason} -\u003e send_resp(conn, 404, reason) |\u003e halt()\n    end\n  end\nend\n```\n\n### Extending Nabo\n\nBy default Nabo uses JSON for post metadata and Markdown for post excerpt and\nbody, but if you prefer them in other format, you are encourage to write your\nown parsers.\n\n```elixir\ndefmodule MyBBCodeParser do\n  @behaviour Nabo.Parser\n\n  def parse(binary, options) do\n    BBCode.to_html(binary, options)\n  end\nend\n```\n\nThen configure your parser to the repo.\n\n```elixir\ndefmodule MyRepo do\n  use Nabo.Repo,\n      root: \"path/to/posts\",\n      compiler: [\n        body_parser: {MyBBCodeParser, []}\n      ]\nend\n```\n\nAnd that's just it!\n\nSee the [documentation](https://hexdocs.pm/nabo) for more `Nabo.Repo` options.\n\n## Q\u0026A\n\n\u003e How does Nabo work?\n\nNabo parses all posts in the configured repo in **compile-time**, keeps them in the module, and returns\nthem when you ask in **run-time**.\n\n\u003e Why this post engine does not support generating static html like Jekyll and\n\u003e such?\n\nNabo is not meant to replace Jekyll since Jekyll has done their job really well\n(trust me the previous version of my blog was built with Jekyll). But Nabo takes\nanother approach and is designed to integrate with other components in your\napplication. If you want to build a blog with more controllable functions like\ncomments or traffic count, then Nabo might fit your needs. If you need a minimal\nversion of static html blog that can play well with Github page, then Jekyll\nwould probably be your choice.\n\n\u003e Why Nabo does not support template, router, controller or server?\n\nAs mentioned, Nabo is designed to be simple and integrate-able with other\ncomponents in your application so it does not presume your needs.\n\nIf you want routing or templating, you can easily integrate Nabo to Phoenix\nor Plug.\n\n\u003e How customizable and extendable is Nabo?\n\nNabo uses JSON for metadata and Markdown for post excerpt and body by default,\nthat is quite an easy decision. But they are **optional**.\n\nYou can control the format of all the three components mentioned above, even the\ndelimiter between them. Nothing is going to stop you to have your own XML metadata,\nMarkdown for excerpt, and BBCode for post body.\n\n## Websites built with Nabo\n\n* [hqc.io](https://hqc.io)\n* [quan-cam.com](https://quan-cam.com)\n\n## Development and issue report\n\nIf you have any issues or ideas, feel free to write to https://github.com/qcam/nabo/issues.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqcam%2Fnabo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqcam%2Fnabo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqcam%2Fnabo/lists"}