Datastore to store dimer websites as JSON

Dimer is an open source project and CMS to help you publish your documentation online.

We believe every project/product is incomplete without documentation.
We want to help you publish user facing documentation, without worrying about tools or codeto write.

Dimer datastore

Dimer datastore saves the websites, their versions and documents for each version.

The datastore operates on JSON flat files and exposes API to mutate and read the store.


npm i @dimerapp/datastore

# Yarn
yarn add @dimerapp/datastore

Data Structure

Following is the data structure of all the nodes inside the store. The requiredproperties are required to mutate the store.


Site is a given website, with it's own domain.

domainStringNOThe domain of the website. If it's stored on dimer servers, then this is the subdomain test.dimerapp.com
cnameStringNOCNAME to dimer subdomain
settingsObjectNOAn arbitrary object containing website settings. This is usually used by the themes


Zones are the way to divide sections of your website docs into multiple top levels. For example: Guides, API, FAQ'sand so on.

slug (unique)StringYesThe slug to be used for uniquely identifying the zone.
nameStringNoThe display name for the zone
versionsArrayYesThe versions for the zone


Versions for a given zone. When your are not using zones, then the versions become the part of a virtual zone.

no (unique)StringYESThe version number. It must be URL friendly
nameStringNoVersion no will be used as the name if not defined.
defaultBooleanNoIs this the default version for documentation. If not defined, the greatest number will be considered as the default version.
depreciatedBooleanNoIs this version depreciated
draftBooleanNoIs this version a draft


The documentation node associated with a version always.

contentObjectYesThe objectof nodes, returned by @dimerapp/markdown.
permalink (unique)StringYesThe unique permalink for the doc. This is the URL people will visit to read the doc
titleStringYesThe titlefor the document. First h1will be used if missing.
jsonPath (unique)StringYesThe relative path, where the contentshould be saved
summaryStringNoThe document social summary. If missing will be fetched from the content.
redirectsArray[String]NoAn array of permalinks to be redirected to this document.


After installation you can grab the datastore as follows and save documents.

const Datastore = require('@dimerapp/datastore')
const Context = require('@dimerapp/context')

const ctx = new Context(__dirname)
const store = new Datastore(ctx)

await store.load()

load(clean = false)

Load the data store to start mutating it, if store is not loaded, hard exceptions will be raised.

Also when you pass clean=true, it will load the store from a clean slate. It is helpful, when you want to build documentation from scratch.

await store.load()

// from clean slate

await store.load(true)

saveDoc(zoneSlug, versionNo, filePath, doc)

Save a new doc to the datastore.

  • The slugfor the zone. If missing, it will be created on the fly.
  • If the version is missing, it will be created on the fly.
  • If filePathexists, the doc will be updated.
  • If permalink exists, an exception will be raised.
const markdown = new Markdown('# Hello world')
const content = await markdown.toJSON()

// save actual doc
await store.saveDoc(
    permalink: 'introduction',
    content: content

// update meta data to database
await store.persist()

removeDoc(zoneSlug, versionNo, filePath)

Remove doc from the store.

await store.removeDoc('guides', '1.0.0', 'introduction.md')

// update meta data to database
await store.persist()


Syncs the zones inside the db. Also versions for each zone will be synced automatically. Each zone will have a diff node for versions too.

const { added, updated, removed } = await store.syncZones(zones)
console.log(added.versions) // { added: [], updated: [], removed: [] }

syncVersions(zoneSlug, versions)

Sync an array of versions with the existing one's. Since all versions are saved inside the config dimer.jsonfile, it is impossible to detect which version was added and which was removed to perform individual operations like add, remove. For the very same reason, datastore exposes the API to sync them.

await store.syncVersions('guides', [
   no: 'master',
   name: 'Version master',
   default: true
   no: 'v4.0',
   name: 'Version 4.0'
   no: 'v3.0',
   name: 'Version 3.0',
   depreciated: true

// update meta data to database
await store.persist()


Returns an array of saved versions.


getTree(zoneSlug, versionNo, limit = 0, withContent = false, attachVersion = false)

Get an array of all the docs. Ideally you want this array to create a navigation menu and then on each request, you can ask for the doc content. However...

  • You can pass withContent=trueand the array will have the actual content for the doc too.
  • Setting limit=0will return all the docs.
  • All docs will be grouped by categories.
  • When attachVersion=true. Each doc will contain it's version node.
const tree = await store.getTree('guides', 'v4.0')

// output
   category: 'Getting started',
   docs: [{
     permalink: ''

getDoc(zoneSlug, versionNo, filePath, attachVersion = false)

Returns the doc meta data and it's content.

  • When attachVersion=true. Doc will contain it's version node.
const doc = await store.getDoc('guides', 'v4.0', 'introduction.md')

getDocByPermalink(zoneSlug, versionNo, permalink, attachVersion = false)

Returns the doc by it's permalink.

  • When attachVersion=true. Doc will contain it's version node.
const doc = await store.getDocByPermalink('guides', 'v4.0', '/introduction')

redirectedPermalink(zoneSlug, versionNo, permalink)

Returns the new permalink at which the doc must be redirected.

const redirectTo = store.redirectedPermalink('guides', 'v4.0', '/old-introduction')

if (redirectTo) {
  // redirect to this location


Sync the configfile with the datastore.

await store.syncConfig(require('./dimer.json'))


Returns the synced config

const config = store.getConfig()


The datastore builds a search index based on elasticlunr, which can be used for indexing a individual version and then performing search queries for same.


await store.indexVersion('guides', 'v4.0')

And then later search

const results = await store.search('guides', 'v4.0', 'Yaml')

Following will be the output of search results

    ref: '/yaml-front-matter',
    title: {
      score: 3.10,
      marks: [
          type: 'raw',
          text: 'What is'
          type: 'mark',
          text: 'Yaml'
          type: 'raw',
          text: 'frontmatter'
    body: [
        score: 2.984,
        marks: [{
          type: 'mark',
          text: 'Yaml '
          type: 'raw',
          text: 'front matter is used for'

Search languages

The datastore has support for multiple languages to create the search index. Following is the list of allowed and supported languages.

English enis the default language.

  • da (Danish)
  • de (German)
  • du (Dutch)
  • es (Spanish)
  • fi (Finnish)
  • fr (French)
  • hu (Hungarian)
  • it (Italian)
  • ja (Japanese)
  • no (Norwegian)
  • pt (Portuguese)
  • ro (Romanian)
  • ru (Russian)
  • sv (Swedish)
  • th (Thai)
  • tr (Turkish)
await store.indexVersion('guides', 'v4.0', 'de')

If your content is written in the mix of multiple languages, then you can pass an array of languages instead.

await store.indexVersion('guides', 'v4.0', ['de', 'en'])

Change log

The change log can be found in the CHANGELOG.mdfile.


Everyone is welcome to contribute. Please take a moment to review the contributing guidelines.

Authors & License

thetutlageand contributors.

MIT License, see the included MITfile.







  • interface-datastore

    datastore interface interfacedatastore (https://img.shields.io/badge/made%20byProtocol%20Labsblue...

    1 年前
  • datastore-pubsub

    Responsible for providing an interfacedatastore compliant api to pubsub datastorepubsub (https://...

    12 天前
  • datastore-level

    Datastore implementation with level(up|down) backend jsdatastorelevel (https://img.shields.io/bad...

    1 年前
  • datastore-fs

    Datastore implementation with file system backend jsdatastorefs (https://img.shields.io/badge/mad...

    1 年前
  • datastore-core

    Wrapper implmentation for interfacedatastore jsdatastorecore (https://img.shields.io/badge/made%2...

    1 年前
  • datastore

    Datastore Brick(http://github.com/bredele/brickjs) reactive data layer Build Status(https://...

    2 年前
  • @google-cloud/datastore

    Cloud Datastore Client Library for Node.js //: "This README.md file is autogenerated, all changes ...

    2 个月前
  • @edropin/datastore-utility

    Datastore utility for eDropin Datastore Utility functions for eDropin HomePage https://github.c...

    2 个月前
  • @dimerapp/utils

    Handy utilities to keep all other repos DRY and consistent Dimer is an...

    4 个月前
  • @alinex/datastore

    Read, work and write data structures from and to differents locations and formats. Alinex Data Sto...

    4 个月前


扫码加入 JavaScript 社区