Skip to content
/ jaen Public

Serverless CMS framework for ReactJS w/ IPFS and GitHub Workflows.

License

Notifications You must be signed in to change notification settings

snek-at/jaen

Repository files navigation

SNEK Logo

Snek Jaen

This is the official jaen project provided by snek-at. Free, sexy and cutting edge CMS framework for ReactJS.

"A bowl is most useful when it is empty." - Lao Tzu

Report bug Β· Request feature Β· Documentation

Read this readme in a different language: Deutsch

What’s In This Document

πŸ’ͺ Motivation

A CMS should not be the defining feature of a webapp. Neither should E-Commerce or anything other than your code.
ERP integration should not force developers to cut corners.

  • Jaen does not interfere with your user experience.
  • Jean does not challenge your application design.
  • Jaen gives the power back to you.

One thing and one thing only with clean and well documented interfaces. Customizable, extensible and open-source.

Jaen Features

  • A fast, attractive interface for authors
  • Complete control over front-end design and structure
  • Fast out of the box, cache-friendly when you need it
  • StreamField encourages flexible content without compromising structure
  • Excellent support for images and embedded content
  • Powered by blockchain and can be run for free
  • Simple, intuitive "What you see is what you get" editing mode

Roadmap

Feature Shipped Almost There We're Writing the Code Investigating
IndexField βœ…οΈ
Email Support βœ…οΈ
Fixed parent for IndexField βœ…οΈ
TextField βœ…οΈ
Dynamic Routes βœ…οΈ
ImageField βœ…οΈ
BlockContainer βœ…οΈ
ChoiceField βœ…οΈ
Gatsby βœ…οΈ
PdfField βœ…οΈ
LinkField βœ…οΈ
Converter (HELMUT) βœ…οΈ
Smart Converter (SMARTMUT) βœ…οΈ
E-Commerce βœ…οΈ
User Management βœ…οΈ
Email Templates βœ…οΈ
Development Tools βœ…οΈ
Snek Editor βœ…οΈ
YT Tutorials βœ…οΈ

Msg inspiring PPL

Chasing ones own tail is not inspiring.

Disclaimer

Not for crybabies. Do not touch if you are afraid of being scratched a little.

πŸš€ Get Up and Running in 5 Minutes

Generate from template Generate Jaen on GitHub

Generate from template Important public and no branches
image image

First Deployment

The GITHUB_TOKEN has limitations for the first deployment so we have to select the GitHub Pages branch on the repository settings tab. After that, follow the instrucions shown in the pictures below to deploy successfully.

First deployment failed Go to the settings tab
image image
Select branch Deploying again and succeed
image image

Deployment Options

We recomend to use Visual Studio Code as IDE either in a codespace or using local setup.

Codespace Setup

The easiest method is to use a GitHub Codespace (in beta). Just create a GitHub Codespace from the Code menu. Wait for the Codespace to complete provisioning. When the Codespace has completed provisioning, open a terminal window (Ctrl-`, Control-backquote) and:

  • Create .env file and set PUBLIC_URL
  • Start a local copy of the docs site with yarn start
  • Or build a local copy of the library with yarn run build

Local Setup

If you decide to set up locally, make sure you have the following prerequisites:

  • Use yarn install to install all dependencies
  • Start a local copy of the docs site with yarn start
  • Or build a local copy of the library with yarn run build

The demo site will now be accessible at http://localhost:8000/.

Troubleshooting

  • You have to use yarn instead of npm. If you decide to use npm you might run into errors.

If you encounter any other issues getting this template to work, we ask you to report it so that we can improve the documentation.

Editing

To edit the page you have to log into the CMS.
The standard user for this is snekman and the password for the account is ciscocisco.

πŸ’» How to Code

Overview

Page Settings

Property Type Description Wiki Tutorial
TemplateName string The TemplateName defines the name of your template in the context of the CMS.

Fields

Field Properties Description Wiki Tutorial
TextField fieldName
initValue
rtf
TextField can be used to add editable texts to your page. βœ…οΈ
ImageField fieldName
initValue
The ImageField is used to provide editable images that are hosted on the ipfs. βœ…οΈ
BlockContainer name
reverseOrder
blocks
wrap
wrapProps
With a BlockContainer you can build your own React-Components with editable content and repeat them as often as you like. βœ…οΈ
IndexField fieldName
fixedSlug
onRender
The IndexField provides you with the oppertunity to easily build links, buttons and more pointing to your subpages. It is also useful for building cards that rely on content from childpages.
With the fixedSlug property you can decide which page the childpages are pulled from.
βœ…οΈ
ChoiceField fieldName
options
initValue
onRender
onRenderPopover
The ChoiceField allows you to build React-Components and let the administrator of the page decide which of the components to display. You can achieve this by either providing a popover in which the options can be decided or you can return null in the popover and add an onClick to your component for use-cases in which all the choices are always displayed or for a boolean like behaviour. βœ…οΈ

Page Settings

import {JaenTemplate} from '@snek-at/jaen-pages'

const HomePage: JaenTemplate = () => {...}

HomePage.TemplateName = 'HomePage'

export default HomePage

jaen-config.js

module.exports = {
  remote: 'snek-at/jaen-template',
  plugins: {
    pages: {
      resolve: require('@snek-at/jaen-pages/jaen-register'),
      templates: [require('./src/templates/SamplePage.tsx')]
    }
  }
}

gatsby-config.js

const path = require('path')

const siteMetadata = require('./site-metadata')

module.exports = {
  siteMetadata,
  plugins: [
    '@snek-at/jaen',
    {
      resolve: '@snek-at/jaen-pages',
      options: {
        templates: {
          SamplePage: path.resolve('src/templates/SamplePage.tsx')
        }
      }
    }
  ]
}

Fields

Fields are data blocks that can be used to build React apps which the enduser is able to maintain. Fieldnames have to be unique when they are on the same page. It is advisable to give all the fields descriptive names.

TextField

The TextField is there to provide your react-components with editable content. It requires you to give it a fieldName and an initValue. The fieldName sets the name of the TextField for the CMS and the initValue sets the value the field has before it gets edited. By default the TextField provides you with an editable RichText. If you only need a short one liner for a heading etc. you can set rtf to false to restrict the field.

import {fields, JaenTemplate} from '@snek-at/jaen-pages'

const HomePage: JaenTemplate = () => {
  return(
    <fields.TextField 
      fieldName="home-text"
      initValue="<p>Your text</p>"
      rtf={true}
    />
  )
}

HomePage.TemplateName = 'HomePage'

export default HomePage

ImageField

The ImageField is the Jaen field that allows you to embed images hosted on the IPFS. It requires both a fieldName and an initValue.

import {fields, JaenTemplate} from '@snek-at/jaen-pages'

const HomePage: JaenTemplate = () => {
  return(
    <fields.ImageField 
      fieldName="home-image"
      initValue={{src: 'https://your.source', alt: 'homeimage', title: 'homeimage'}}
      style={{width: '300px', height: '180px'}}
      className="imagefield"
    />
  )
}

HomePage.TemplateName = 'HomePage'

export default HomePage

BlockContainer

Jaen BlockContainers enable you to integrate editable blocks and to use as many of them as you like. You can put them into a Chakra UI wrap and pass props to the wrap. In order to use this field you are required to build a block. You can find an example of a block below.

import {BlockContainer, JaenTemplate} from '@snek-at/jaen-pages'
import {CardBlock} from '...'

const HomePage: JaenTemplate = () => {
  return (
    <div style={{width: '50%'}}>
      <BlockContainer
        reverseOrder={false}
        name="home-blockcontainer"
        blocks={[CardBlock]}
	wrap={true}
	wrapProps={{justify: 'center', spacing: '5'}}
      />
    </div>
  )
}

HomePage.TemplateName = 'HomePage'

export default HomePage
Chakra UI Wrap Example

This example displays five boxes of varying colors with a 1 rem space between them in a flex that goes into the next row if the content is too wide. It also centers the boxes.

import {Wrap, Box} from '@chakra-ui/react'
import {fields} from '@snek-at/jaen-pages'


const Component = () => {
  return(
    <Wrap spacing="1rem" justify="center">
      <Box boxSize="300px" bg="red"/>
      <Box boxSize="300px" bg="teal"/>
      <Box boxSize="300px" bg="orange"/>
      <Box boxSize="300px" bg="blue"/>
      <Box boxSize="300px" bg="green"/>
    </Wrap>
  )
}

IndexField

If you want to link to childpages of a slug, the IndexField is your friend. The fixedSlug property is not required. When none is provided, the children of the page the IndexField is on are used. If you like, it is possible to specify the parentpage and the onRender property allows you to build cards, teasers, buttons and more to your subpages.

import {fields, JaenTemplate} from '@snek-at/jaen-pages'

const HomePage: JaenTemplate = () => {
  return (
    <fields.IndexField
      fieldName="home-indexfield"
      fixedSlug={'pageId'}
      onRender={(page) => {
        return(
	  [...]
	}}
    />
  )
}

HomePage.TemplateName = 'HomePage'

export default HomePage

ChoiceField

The ChoiceField allows you to build React-Components and let the administrator of the page decide which of the components to display. You can achieve this by either providing a popover in which the options can be decided or you can return null in the popover and add an onClick to your component for use-cases in which all the choices are always displayed or for a boolean like behaviour.

import {fields, JaenTemplate} from '@snek-at/jaen-pages'

const HomePage: JaenTemplate = () => {
  return(
    <fields.ChoiceField 
      fieldName="home-choice"
      options={[...]}
      onRenderPopover={(selection, options, select) => {
        return [...]
      }}
      onRender={(selection, options, onSelect, isEditing) => {
        return [...]
      }}
    />
  )
}

HomePage.TemplateName = 'HomePage'

export default HomePage

Blocks

The Block is the keystone of the BlockContainer. With the help of blocks you can build complex React-Components with editable content. All available fields can be used inside a block.

import {JaenBlock, fields} from '@snek-at/jaen-pages'

const CardBlock: JaenBlock = () => {
  return (
    <div className="card">
      <h1>
      	<fields.TextField 
      	  fieldName="blocktext"
	  initValue="<p>this is your heading</p>"
	  rtf={false}
	/>
      </h1>
      <fields.ImageField 
        fieldName="blockimage"
	initValue={{src: 'https://your.source', alt: 'yourAlt'}}
	style={{width: '300px', heigth: '180px'}}
      />
    </div>
  )
}

CardBlock.BlockName = 'CardBlock'
CardBlock.BlockDisplayName = 'Card'

export default CardBlock

🐞 How to Report a Bug or Request a Feature

Have a bug or a feature request? Please first search for existing and closed issues. If your problem or idea is not addressed yet, please open a new issue.

🀝 How to Contribute

GitHub last commit GitHub issues GitHub closed issues

Please read through our contributing guidelines. Included are directions for opening issues, coding standards, and notes on development.

All code should conform to the Code Guide, maintained by snek-at.

πŸ’š Thanks

We do not have any external contributors yet, but if you want your name to be here, feel free to contribute to our project.

πŸ’Ό Creators

Avatar schettn Avatar kleberbaum Avatar petute
Nico Schett Florian Kleber Daniel
Petutschnigg

πŸ€” FAQs

Q: What do the roadmap categories mean?

  • Shipped - Hopefully you are enjoying it! Give us feedback on how it is working!
  • Almost There - We are applying the finishing touches. Things in this bucket you can expect to be shipped within 2-4 weeks.
  • We're Writing the Code - Actively in development, we are trying to get this out to you in a good state as soon as we can.
  • Investigating - We're thinking about it. This might mean we're still designing, or thinking through how this might work. This is a great phase to send how you want to see something implemented! We'd love to see your usecase or design ideas here.

Q: Why are there no dates on your roadmap?

A: Because we know things change and we want the room to do the right thing by fixing security issues as they come up or helping people out where they need. This means we might have to change our priorities and don’t want to let people down.

Q: How can I provide feedback or ask for more information?

A: Please open an issue in this repo! If the issue is a bug or security issue, please follow the separate instructions above.

Q: How can I request a feature be added to the roadmap?

A: Please open an issue! You can read about how to contribute here. Community submitted issues will be tagged "Proposed" and will be reviewed by the team.

🀯 Trivia

Name:

In Austria the first month of the year is called "JΓ€nner" since we started working on this project in January we decided to name the project Jaen.

Pronounciation:

The name Jaen is pronounced (JΓ€n)ner [ˈjΙ›n] or (Jan)uary [ˈdΚ’Γ¦n].

Password:

The standard password in Jaen is ciscocisco. The origin of this password were back at our time in school. Most of us went to school for network engineering and in the cisco courses the standard password would always be ciscocisco.

Releases:

Every one of our Jaen releases has it's own theme song. Have fun with it.

Mascot:

The inofficial mascot of this project is a girl holding an electric guitar.

<3

πŸ“ Copyright and License

GitHub repository license

Use of this source code is governed by an EUPL-1.2 license that can be found in the LICENSE file at https://snek.at/license