Safe-CMS - Censorship is a thing of the past

Announcing the creation of a simple-to-use CMS engine built on top of the Safenetwork.

Progress updates
2018-02-24 (version 0.0.3)
2018-02-25 (version 0.0.5)
2018-02-26 (version 0.0.6)

I’ve begun the development of a React/Node CMS engine styled around Wordpress - I’m aware of the already existing Safepress project, however I’m wary that it’s been in development for a few years now.

The project will allow the following:

  • Creation of a host / safe network domain for your blog
  • Creation, updating and deleting of posts (stored as MutableData objects)
  • Creating a custom template to wrap the posts
  • (or) Selecting between a few simple pre-made (but customisable templates)


The template will be stored as a single Javascript file (stored as a MutableData object) which will be loaded when the blog post is loaded, allowing the use of a single PUT for modifying your template (instead of having to modify all of the posts).

Should the user decide to create their own template, they will only have to create HTML, JS and CSS, the conversion process from flat content to the compiled template file will be performed automatically when publishing your template (including linting, error checking, etc, to ensure no PUTs are wasted.)

Home page

The home page of your blog will be a post listing page which will have to be updated every time a new post is created (or an old post deleting).

Persistence and efficiency

To reduce the number of PUTS / storage cost required (and the read strain on the SAFE network) the posts & templates will be persisted simultaneously to the editor’s local file system, allowing posts to be in a “draft” state where the user can edit and view their own posts.

Publishing mechanism

The fantastic Safe NodeJS app library will be used for persisting MutableData objects to the SAFE network.

Release date

The first release candidates with this core functionality (code on Github, executables) will be available by the end of February.

Known Limitations:


Shane Armstrong (@shane)
Software engineer with 6 years experience of building massively scale-able web applications in Rust and PHP5/7.

Andy Alban (@AndyAlban)
Frontend software developer with experience building React applications.

Thank you for reading.


Sounds brilliant Shane and I will be happy to support this.

My only wish with working on and promoting safepress has been to help get this kind of project built, so I hope you get lots of support from the community.

Your approach is very well thought out IMO :+1: Good luck!


Thanks a lot @happybeing, it means a lot to get that kind of validation from you - I took a lot of inspiration from your project in my initial thoughts about how it would work. Since this is all going to be released under LGPL3, hopefully we’ll be able to get some value from each other’s projects and give the SafeNet two options to choose between. :slight_smile:


Yes, and I’m happy to put my efforts into supporting your work if I have anything to offer (and the time!) :slight_smile:


Super wow @Shane
This is what makes the SAFE Network valuable

Keep up the good work can’t wait to try this out :stuck_out_tongue:

Amazing that you even know the PUT costs, like the “draft” feature.


Awesome project! I am eager to see it up and running =) :face_with_monocle::v:


Now that is really cool !! So nice to see people creating use for the network :slight_smile: I’m eager to see it in action, and to learn by reading the code !


Hey guys, I figured it would be best for this project to build anticipation if I post an update here whenever I reach any sort of milestone (so most likely every few days) - so here’s the first.

Frontend framework

As of right now, I have ReactJS running how I want it to, rendering the different page views when the menu items are clicked on and posts can be created, here is how the post listing page looks at the moment (it’s worth mentioning the “Published” value is spoofed for now, I’ll explain why further below):

(The app looks sharp, no where near as blurry as this image, for some reason it seems to have been compressed during upload)

I’m using the Flux library to pass around state and delegate events when data is changed.

Server application

I have settled on Node Express.js for running the “server” within the compiled executable. This server will act as middleware between the frontend (React) and the SafeNet, allowing me to take advantage of the native filesystem.

As of right now, when posts are created, they are simply persisted to the local filesystem (so closing and re-opening the app preserves the posts!) and the next step is for me to download the Safe Node JS app framework and pull out the library functions I need to interface with the SafeNet.

I’m using abstraction layers wherever anything to do with the operating system / arch (32/64) are concerned, so the app is going to support “every” operating system, where “every” is the subset currently supported by the Nexe compilation tool (so that’s Windows, OSX, popular OS distributions built atop the linux kernel)

What’s left

Things I still have left to do for now are:

  • Integrate the local app with the Safe Authenticater
  • Integrate the local filesystem posts with the remote SafeNet posts
  • “copy” (steal) the code from the Safe Web Hosting Manager example app which deals with the creation of public IDs and domains within them
  • Figure out how to load secondary safe://object.path files within safe:// websites, I’m assuming this is already supported natively by the browser, but I don’t want to count out any complications
  • Build the tool for converting the template files from HTML/CSS/JS to the single JS executable
  • Build a few sample templates to export with the app

I feel like I’m in a good spot after a couple of days of working on this part-time, and have a solid understanding for the problem space and what to do next. I don’t foresee any major blockers and I’m happy and excited with the progress I’ve made thus far.


Well done Shane. Look forward to using this.


A double whammy of updates thanks to the weekend!

I’ve been working on the post-editing page today and have a more presentable design for it now, so I’m happy to share that with you:

The content above is as follows:

  • Modify the title of the post, this can be any UTF-8 character with a maximum length of 64 characters.
  • Modify the “slug” or “post URL”, the actual URL you would be editing here would be “my-first-post” (and the input auto updates to show only this when you click on it. The “domain” or safe://local.shane is modified on the Settings page.
  • Modify the content, I’m using React Draft WYSIWYG for the post content, for now I’ve decided to remove the image functionality and I’ll probably release without it then have images, audio and video uploads for V2.0.0
  • An indicator for the current state of the post, “drafts” are stored locally while editing them, “published” have been persisted to the SafeNet and “edited” are published posts you have re-edited locally which need to be published again.
  • The “Safe Draft” and “Publish to SafeNet” buttons obviously achieve the functions above.

Planned functionality

After doing some more investigation in to the safe browser, it seems like it has no issue with loading secondary assets (images, css, etc) within a safe:// web page, so that makes my plan of storing the template files as a single JS MutableData object workable and I’ll probably get started working on the template logic some time in the next 2 weeks after I’ve got SafeNet persistence working.

Another day of great progress and I’m still happy with how the project is going.


You are doing an amazing job!


Great job man!
(+20 characters)

1 Like

Looks great Shane. Can anyone point me to more information regarding potential put costing algorithms.

1 Like

Thanks a lot guys, really appreciate the support.

@Guybrows the whitepaper is here but I’ll explain it as simply as I can:

A PUT is a request to store a single chunk on the network (a file may contain many chunks). The maximum chunk size is 1 MB.

1MB of data costs 1 Safecoin, however it’s worth mentioning that the 1MB isn’t used per chunk you upload, but rather by amount of data you upload. If you have 1MB and upload a single PUT containing 200KB, you will have 0.8MB of data remaining before you have to add more Safecoin to your account.

I show PUT cost above because all things being equal, I have no control over the size of people’s blog posts (besides showing helpful recommendations in the admin), but PUT cost is a useful number to calculate network load - more PUTs means more network requests, so reducing the number of PUTs reduces network load.

In terms of the actual dollar cost of making a blogpost, it’ll be calculated as such:

price of 1 safecoin * blog post size in mb

So if Safecoin is priced at $0.65 and you’re uploading a 200KB blog post, the dollar cost will be as follows for the required PUTs:

$0.65 * 0.2 = $0.13


Thanks. Surely there is more flexibility to the storage cost. If safe coin was 10 dollars, highly likely through speculative holding alone. Then we would have the same post at a cost of 2 dollars. Ouch , expensive post about my football sticker collection.


I believe there is some mechanism by which the network corrects for coin cost, but I haven’t been able to find any documentation on it - I’ve seen it in discussions but haven’t yet come across an RFC or whitepaper for it.

1 Like

This isn’t quite it. The amount of storage per SafeCoin is not fixed, but adjusts automatically so that the cost of storage is expected to be very low compared to alternatives.


I love this thing more by a minute.

I wonder what would the whole principle of paying for the data storage do for the way people present their ideas and themselves. An authoritative censorship may be a thing of the past, but what about self-censorship? I expect much more refined and well thought out content.

What would be the downside?

1 Like

Do you have the whitepaper / RFC / Pull request for that? I would love to read how it’s achieved

Here’s the full list of active RFCs, the info you want is in 0012: