@MoOx MoOx released this May 24, 2018 · 19 commits to master since this release

Hopefully, the last beta

We are very close to our final and stable release for v1. Why we didn't ship
this version already? Some people like to move fast & break things. But we
wanted to have a correct design for the v1 so future majors version won't break
too much things.

What we did for v0.x was an experiment and we learned a lot of things by running
this in production on moderate websites. We have spent a lot of brain energy to
make a scalable & flexible solution with a small API surface.

We have designed an architecture that follow React way of thinking, by offering
a centralized lifecycle. With that in
mind we have adjusted our goal and make React & Webpack, 2 core pieces of v0.x,
first class plugins in our v1.x. This opens up lot of nice things to support
React or Webpack alternatives.

Documentation is a work in progress 🎉

First thing to celebrate, we started to work on our website! You can now find
documentation for the core and the
react preset tutorial! More things will

2 small breaking changes

Below you will find 2 small breaking changes, very easy to adjust (that will
probably consist of adding content in front of all your current existing query
to our content api or to adjust your configuration).

🚨 @phenomic/core: content options now supports multiples entries and globs
by @MoOx

All your previous queries won't work with this breaking change but don't
worry, it's very easy to adjust your code.

We are sorry to add a breaking change now, but it's for the better.

Solution 1 (recommended): You will have to add "content/" in front of all
your path in your queries. Why? It's for being more explicit and also be able
to support multiples sources (multiples folders) to avoid duplicate names
without a weird configuration. The upgrade is pretty easy.

For example

const HomeContainer = withPhenomicApi(Home, props => ({
  posts: query({
    path: "posts"

Will become

const HomeContainer = withPhenomicApi(Home, props => ({
  posts: query({
    path: "content/posts"

Solution 2 (for lazy people): You can keep the previous behavior very easily
by using this value for content option: "": {root: "content", globs: ["**/*"]}. You can throw that in your package.json in a phenomic like this:

  "phenomic": {
    "content": {
      "": {root: "content", globs: ["**/*"]}
    "presets": ["@phenomic/preset-react-app"]

🚨 @phenomic/plugin-rss-feed: now lookup in content/posts by default.
by @MoOx

To get previous behavior back, just use this configuration (adjust to match

  "phenomic": {
    "presets": ["@phenomic/preset-react-app"],
    "plugins": [
          "feeds": {
            "feed.xml": {
              "query": {
                "path": "content/posts"


🐛 @phenomic/plugin-renderer-react: Handle scroll like it should (to top or to the hash if any)
by @MoOx

🐛phenomic/plugin-collector-files: correctly clean extensions from filename for id (not only md|json but all extensions by the plugin loaded at runtime)
by @MoOx

Tons of small improvements

As we started to actively working on our documentation, we have added tons of
small improvements.

@phenomic/plugin-renderer-react: add render + callback option to createApp/renderApp for custom rendering
by @MoOx

This commit allows you to use a custom render() function. This way to render the
app is required by some solutions that needs a custom wrapper for styles
pre-rendering (eg: react-native-web).

🎉 examples/react-native-web-app
by @MoOx

@phenomic/core: add socketPort option (and switch to 3334 since 1415 can be used by dbstar)
by @MoOx

@phenomic/core: Improve error shown from database access
by @MoOx

@phenomic/core: Improve error message from database not found entry
by @MoOx

🔥 Add a new helper to extract meta from body nodes (title + headings list)
by @MoOx

This helper is used in @phenomic/plugin-transform-markdown and
@phenomic/plugin-transform-asciidoc to automatically add a title meta
even if you don't have frontmatter. Pretty cool for files that you don't
control. This helper also returns a list of headings in your content, which is
pretty convenient to make a table of content at the top of you page or in a

@phenomic/plugin-transform-markdown: add title fallback extracted from markdown body if no title is in the frontmatter + add a list of markdown headings
by @MoOx

@phenomic/plugin-transform-asciidoc: add title fallback extracted from markdown body if no title is in the frontmatter + add a list of markdown headings
by @MoOx

@phenomic/plugin-transform-json: add title fallback
by @MoOx

@phenomic/core: better display in case of error during start/build
by @MoOx

@phenomic/core: add options to sort db results
by @MoOx

This feature is pretty awesome and allows you to add custom order to your query.
As a good example, we wanted to sort our showcase with the following algorithm:

  • Sites with a flag curated first
  • Sites with many tags
  • Sites with tags "blog" at the end.

In order to do so, we have introduced this option and we hope you will like it.
You can check out the
documentation for db.sortFunctions
and take a look to the
one we use for the showcase.

@phenomic/cli: add preview command
by @MoOx

@phenomic/core: add preview command to build & serve results
by @MoOx

Now you can run

phenomic preview

This will build and serve the website, to mimic production (as you will have the
pre-rendered files and the client side reconciliation).


@MoOx MoOx released this Apr 7, 2018 · 112 commits to master since this release

Stable 1.0.0, we are almost there!

This release is probably the penultimate before the stable release.
It brings us 2 majors things:

  • 🎉 For React users, 2 methods, supported via the new withInitialProps HOC, allows you to consume any kind of data (not just Phenomic API but any kind of REST APIs, GraphQL APIs for CMS etc) via static async getInitialProps(). This API, inspired by Next.js is not alone as it comes with another new method for the pre-rendering step, called static async getAllPossibleUrls().
  • 💪 We adjusted 2 transform plugins (markdown and asciidoc) so you can directly pass to those the unified plugins you want to use.

This release is an important step for us as it brings us our missing pieces to be happy with Phenomic current state.
Stay tuned for the final release, that will be done at the same time as we will publish documentations on the website.

🤩 We also created a new react-app-blog example that you can use as a good starting point to create any site (not only a blog - and we plan to push more examples when we will hit stable 1.0.0).
This starter includes some pages, some posts, and the usage of our new fresh API to create pages from github data (but you can just use this and replace with any kind of API) to generate client side and static generated pages from those data!
For the architecture, we used something simple, with a few components for header/footer with differents layouts etc. We also included a standard error page (used for 404).
For the styling, we didn't wanted to do something too opinionated and also something too old school (CSS in dedicated files since we all love CSS-in-JS), so we took an simple approach in the middle, with a CSS style tags per components. This allows CSS lover to just extract the CSS in files, and CSS-in-JS lovers to easily convert in places the styles. Remember that we have plenty of examples to know how to handle CSS via any kind of solutions.
You will find a visual preview at the end of this post.


⚠️ @phenomic/plugin-renderer-react: createContainer is now withPhenomicApi(you will get a warning until you update your import) by @MoOx
Not a breaking change yet, but will be during stable 1.0.0 release.

🐛 @phenomic/plugin-collector-files: fix edge case when you request an index file with an id (db was not correctly filled) by @MoOx

🐛 @phenomic/core: fix edge case when you request an empty id (for index) by @MoOx

🐛 @phenomic/core: fix time log between pre-rendering and after build hook by @MoOx

🐛 @phenomic/plugin-transform-markdown: code is now highlighted without failing if language is not recognized by @MoOx

🚨@phenomic/plugin-transform-markdown: remark/rehype plugins order have been changed a bit by @MoOx
This should only affect you if you were relying on (previously broken) code highlight.

🚨/ @phenomic/plugin-transform-asciidoc: plugin have been update to work like markdown. by @MoOx
Previously we never tested this plugin on a real project so we are not sure it has ever worked correctly 😁.

@phenomic/plugin-transform-markdown: you can now specifiy options for highlighting language unsupported by default by @MoOx

@phenomic/plugin-transform-markdown: you can now choose between json/html mode for the rendering via output option by @MoOx

@phenomic/plugin-transform-markdown: new plugins option to replace unified/remark/rehype plugins by @MoOx

@phenomic/plugin-transform-asciidoc: you can now choose between json/html mode for the rendering via output option by @MoOx

@phenomic/plugin-transform-asciidoc: new plugins option to replace unified/remark/rehype plugins by @MoOx

@phenomic/helpers-transform: new package that exposes stuff shared across transform plugin by @MoOx

@phenomic/plugin-renderer-react: withInitialProps HOC that supports static async getInitialProps({pathname, params}) and static async getAllPossibleUrls({path}) by @MoOx
This allows to generate pages with any source of data (fetch from any kind of REST, Grapql APIs).
Inspired by Next.js.
You can check our example of usage in our react-app-blog example

@phenomic/plugin-renderer-react: withPhenomicApi HOC (previously named createContainer) by @MoOx

🎉 examples/react-app-blog: a sweet starter to discover phenomic with react and make a blog in a few minutes by @MoOx

Preview of the homepage of the new react-app-blog example



@MoOx MoOx released this Mar 30, 2018 · 133 commits to master since this release

This release might include breaking changes for you.

This is one of the final step before stable 1.0.0!
The breaking changes included in this release are for the best. We have worked hard so you can be able to use simple options for plugins, exactly like babel.
More on this below.

If you use @phenomic/preset-react-app without any customisation, you are probably all good

  • Just be careful if you where using JSON
  • If you code was working without any warning, you don’t have anything to do except looking for hasNextPage & hasPreviousPage. If you were still using those, just replace your test with the presence of nextorprevious` directly.

If your are using custom plugins, you will have to update some signatures.

🚨Breaking changes

🚨 Remove deprecated attributes for pagination and routes by @MoOx

🐛 🚨 @phenomic/plugin-transform-json: support array by passing all js on as data (+use a partial version is accessible) by @MoOx

Previously, using JSON files that were array was broken. We were spreading JSON like if it was an object. We adjusted the behavior that might affect partial (when you fetch list via queries) if you had a "partial" entry in your JSON (edge case).
Reach us on our community tools if you struggle updating.

🚨 @phenomic/plugin-transform-markdown: upgrade to gray-matter@3 by @MoOx

If you are using something else than JSON, YAML of JavaScript in your front-matter, please open an issue so we can improve the situation so we can work on allowing engine option https://www.npmjs.com/package/gray-matter#optionsengines

🚨 @phenomic/core: collect method for plugin should now be collectFile. by @MoOx

🚨 @phenomic/core: many plugin methods have their signature that have been updated by @MoOx

Please check flow definitions until docs is online (major change is that config is not send since plugin receive it when it's created).
All signatures for plugin have been adjusted. Please take a look if you are a plugin author.
See https://github.com/phenomic/phenomic/blob/954fbe16f20a51af90cbd6a25502da1426e4bdc5/flow-typed/phenomic.js#L159-L202

New features and improvements

@phenomic/*: we can now configure every plugins from phenomic config. by @MoOx

See last item of this list to see an example ;)

@phenomic/core: support baseUrl option in configuration by @MoOx

You can now send a baseUrl in phenomic configuration. This allow website to work at a folder level of a domain (eg: http://domain.tld/root/).

  "baseUrl": "http://mydomain.com/root-of-my-site/“,
  "presets": ["@phenomic/preset-react-app"]

Note that this will directly be reflected during development for your mental health! This means you will have to open http://localhost:3333/root-of-my-site/

@phenomic/core: support .env(.)? files for PHENOMIC_ env vars by @MoOx

Like CRA support REACT_APP_* env var to be passed over to your JavaScript during compilation, you will have access to PHENOMIC_* var that you can define from .env files.
We are using https://github.com/motdotla/dotenv hunder the hood.

@phenomic/core: we added a new plugin api so any plugin can add static or dynamic url on runtime (resolveURLs) by @MoOx

@phenomic/core: renderStatic is now not limited to a single plugin. Multiples plugins (those that have a resolveURLs can now render static files). by @MoOx

@phenomic/api-client: import fetchRestApi from "@phenomic/api-client/lib/fetch"; to fetch phenomic api directly. by @MoOx

This method is mostly for plugin developers.
Calling this method should be made with import query from "@phenomic/api-client/lib/query”;.
Be careful to use this method wisely as it won’t be magically pre-rendered for all end point unless a plugin handle the static rendering of the resource.

@phenomic/plugin-bundler-webpack: respect baseUrl option by @MoOx

@phenomic/plugin-bundler-webpack: inject NODE_ENV + PHENOMIC_* env var (PHENOMIC_ENV & PHENOMIC_APP_BASENAME for now) by @MoOx

@phenomic/plugin-renderer-react: expose enhanced Link component that respect baseUrl option by @MoOx

@phenomic/plugin-rss-feed: this is now a thing and can generate multiples feed by @MoOx

Example of the config for Phenomic website

  "baseUrl": "http://phenomic.io/",
  "presets": ["@phenomic/preset-react-app"],
  "plugins": [
        "feeds": {
          "feed.xml": {
            "feedOptions": {
              "title": "Phenomic.io",
              "description": "Phenomic news"
            "query": { "path": "news", "limit": 20 }

📝 Various minor docs improvements by @getDanArias


@MoOx MoOx released this Mar 8, 2018 · 153 commits to master since this release

We are on the road to final 1.0.0!

What is planned:

  • We only plan to add an new generic API to fetch any kind of data (like async getInitialProps in Next.js) & a few minor improvements.
  • We will also soon publish a few benchmarks between some well known others static site gen (that might reveal things…).
  • We will try to add a bunch of plugins to show the world what Phenomic can really do.

If you have any question you can ask us on Spectrum or on Gitter.




  • Remove sites in the showcase that were not using Phenomic anymore (or where unavailable).
    We used a script to detect Phenomic on those website that we will run periodically.
    by @MoOx
  • Move the website from docs to website folder, more clear for contributors
    by @MoOx
  • Add a link to our new Spectrum community (by @mxstbr)
  • Add favicons & friends


  • Migration to Circle CI 2.0
  • Readme update
  • PNGs logo added into git repo (previously only sketch & svgs were available)


@MoOx MoOx released this Jan 11, 2018 · 186 commits to master since this release

💥 Includes Breaking changes for Reason users.

This release is mostly a bunch of improvements (with a minor breaking change) for Reason users in addition to a bugfix for an edge case.

💥 Breaking changes (Reason only)

🐛 Bugfixes

⚠️ Deprecation

  • hasPreviousPage & hasNextPage are deprecated, by @MoOx
    Please test directly the existence of previous and next.
    It will continue to work for a while, but will be remove some day.
    This is to make it more straight forward to use pagination in Reason.

💪 Improvements

👌 Improved Example (Reason)

@MoOx worked a lot on the examples/reason-react-app:

  • upgrade to reason-react 0.3.1
  • we switched to es6 for bs generated files
  • we added pagination, like in the JavaScript example
  • we added react-helmet usage (via bs-react-helmet)
  • we reorganized the code and added tiny helpers

♥️ If you have questions, recommendations or improvements to submit, you can reach us on our chat or via the issues


@MoOx MoOx released this Dec 20, 2017 · 207 commits to master since this release

If you were previously relying on the fact that the meta author from a file was magically resolved to a possible authors from your database, you should instead rely on the generic behavior that works with identical names.
This means you should change author: "name" to authors: ["name"]. This will produce the same magic resolution when retrieving content from a single (id based) query.
If you really want the old behavior back, we should think about a generic solution. So please open an issue.


@MoOx MoOx released this Dec 6, 2017 · 230 commits to master since this release

🎉 No breaking changes 🎉

🐛 Reason fix, round 2

Ooops! We forgot to publish .re files for new reason packages.
Fixed by @MoOx in #e010f0f


@MoOx MoOx released this Dec 6, 2017 · 232 commits to master since this release

🎉 No breaking changes 🎉

🐛 Reason fix

Ooops! We forgot to publish bsconfig.json files for new reason packages.
Fixed by @MoOx in #19746b6, reported by @Essential


@MoOx MoOx released this Dec 4, 2017 · 236 commits to master since this release