{"id":44343618,"url":"https://github.com/deer/fresh_blog","last_synced_at":"2026-02-11T13:11:41.356Z","repository":{"id":179910886,"uuid":"655895641","full_name":"deer/fresh_blog","owner":"deer","description":"A plugin for Fresh to create a blog.","archived":false,"fork":false,"pushed_at":"2024-03-31T11:47:27.000Z","size":124,"stargazers_count":15,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-14T19:24:24.575Z","etag":null,"topics":["deno","denofresh","fresh"],"latest_commit_sha":null,"homepage":"https://deno.land/x/fresh_blog","language":"TypeScript","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/deer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-06-19T20:52:32.000Z","updated_at":"2025-08-26T20:50:55.000Z","dependencies_parsed_at":"2024-01-17T09:03:19.348Z","dependency_job_id":"9b4f85bd-ed84-42b9-9bfb-6a3e1d29ea82","html_url":"https://github.com/deer/fresh_blog","commit_stats":null,"previous_names":["deer/fresh_blog"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/deer/fresh_blog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deer%2Ffresh_blog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deer%2Ffresh_blog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deer%2Ffresh_blog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deer%2Ffresh_blog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deer","download_url":"https://codeload.github.com/deer/fresh_blog/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deer%2Ffresh_blog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29333170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T12:42:24.625Z","status":"ssl_error","status_checked_at":"2026-02-11T12:41:23.344Z","response_time":97,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["deno","denofresh","fresh"],"created_at":"2026-02-11T13:11:40.579Z","updated_at":"2026-02-11T13:11:41.350Z","avatar_url":"https://github.com/deer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Coverage Status](https://coveralls.io/repos/github/deer/fresh_blog/badge.svg?branch=main)](https://coveralls.io/github/deer/fresh_blog?branch=main)\n\n## Fresh Blog\n\nThis project provides a\n[Fresh Plugin](https://fresh.deno.dev/docs/concepts/plugins) that allows for the\neasy creation of a blog.\n\nInspired by\n[https://github.com/lumeland/theme-simple-blog](https://github.com/lumeland/theme-simple-blog)\nand\n[https://github.com/denoland/deno_blog](https://github.com/denoland/deno_blog).\n\n## Demo\n\nThe `tests/fixture` folder within this repository provides an example of this\nplugin being used to power a project.\n\n## Features\n\nSo what does this actually do? It registers one middleware to load the posts and\nstash them in a global context for later usage. I'm open to PRs on improving\nthis!\n\nAdditionally, it provides the following routes:\n\n- an `_app.tsx` for the layout (this should be configurable in the future)\n- a `blog/[slug]` route for actually showing posts\n- an `index` route for showing post excerpts and a paginated listing of posts\n- an `author/[author]` route for showing all posts of a certain author\n- an `archive` route for showing all posts, with a listing of tags for filtering\n- an `archive/[tag]` route for showing all posts of a particular tag\n\n## Usage\n\nIn your `main.ts` (or wherever you invoke `start`) add an import like the\nfollowing:\n\n```ts\nimport {\n  BlogOptions,\n  blogPlugin,\n  Localization,\n} from \"https://deno.land/x/fresh_blog@0.0.1/mod.ts\";\n```\n\n(Note: you probably want to use the latest version, which isn't 0.0.1, but don't\ndo this: `https://deno.land/x/fresh_blog/mod.ts` either.)\n\nYou'll need to configure the plugin. An example could be something like this:\n\n```ts\nconst blogOptions: BlogOptions = {\n  title: \"Reed's Blog\",\n  rootPath: import.meta.url,\n  navbarItems: {\n    Archive: \"/archive\",\n    About: \"/about\",\n    Contact: \"/contact\",\n    Projects: \"/projects\",\n  },\n  strings: {\n    lang: \"en\",\n    attribution: \"Author:\",\n  },\n};\n```\n\nThen change your `start` invocation like so:\n\n```diff\n-await start(manifest);\n+await start(manifest, { plugins: [blogPlugin(blogOptions)] });\n```\n\nPut your posts in a `posts` folder at the root of your project. My personal blog\nlooks like this:\n\n```\ntree\n.\n├── README.md\n├── deno.json\n├── dev.ts\n├── fresh.gen.ts\n├── main.ts\n├── posts\n│   └── (lots of posts here)\n├── routes\n│   ├── about.tsx\n│   ├── contact.tsx\n│   └── projects.tsx\n├── static\n│   ├── favicon.ico\n│   └── logo.svg\n└── twind.config.ts\n```\n\nNote how I'm not providing any index file -- that comes from the plugin.\n\n### Separate Index\n\nDon't want the blog listing to be the index page? No problem: simply set your\n`BlogOptions` object to have `separateIndex` set to true. You'll need to provide\nyour own `index.tsx` route in order to avoid errors now. The blog get shunted\ninto a /blog/ route as a result.\n\n### Posts Per Page\n\nThere's also an option to configure the `postsPerPage` which defaults to 10.\n\n### Localization and String Overrides\n\nYou don't like some of the wording built into the blog? Simply provide your own\n`strings` object in the config:\n\n```tsx\nstrings: {\n  lang: \"en\",\n  attribution: \"Author:\",\n},\n```\n\nNote: we provide some built in localizations as well (currently just EN and ES)\nfor you. Feel free to use one of these as a starting point, and then override\nany of the following strings as you see fit:\n\n- attribution\n- nextPage\n- previousPage\n- nextPost\n- previousPost\n- continueReading\n- noPostsFound\n- blogTitleEnding\n- archiveTitleEnding\n- authorTitleEnding\n\n### Notion as a CMS\n\nIf you want to use Notion as a CMS, then you'll need to leverage the `sources`\nproperty in your config. It's currently typed like this:\n\n```ts\nexport type Source = \"local\" | \"notion\";\n```\n\nYou can have both local and notion based posts. In order for things to work,\nyou'll need to create a database that has the following columns:\n\n- slug\n- Date\n- Excerpt\n- Description\n- Draft\n- Author\n- Tags\n\nThe actual content needs to (currently) be in a markdown code block within the\npage. The content in the code block is the only block which will get pulled into\nthe post.\n\nYou also need to configure the following env variables:\n\n- BLOG_NOTION_API_KEY\n- BLOG_NOTION_DATABASE_ID $$\n\n### Post Details\n\nFront matter should be in the following format:\n\n```md\n---\ntitle: \"Collaboration is Great\"\ndate: 2023-6-19 04:38\nauthor:\n  - Reed von Redwitz\n  - Guest Author\ntags:\n  - placeholder\n---\n```\n\nNote that you can also provide authors and tags as single values:\n\n```md\n---\ntitle: \"Single Tag\"\ndate: 2023-7-10\nauthor: Single McTag\ntags: single-tag-test\n---\n```\n\nTo get a snippet (excerpt) to appear on the index page, add the following to\nfunction as a separator within your content:\n\n```md\n\u003c!--more--\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeer%2Ffresh_blog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeer%2Ffresh_blog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeer%2Ffresh_blog/lists"}