? Paper CMS ?
A document-based headless CMS with API + back office.
Made primarly for editorial content management. Stock definitions are modelled after Schema.org vocabulary.
? Check here for a Paper CMS online tryout.
? Default dataset is reseted periodically.
? Use good ol’
or… local quick start ?
# Clone this repo git clone [email protected]:JulianCataldo/paper-cms.git cd paper-cms code ./ # Install all dependencies npm run deps:i # Run and watch API + back office npm run dev # Open back office in browser open http://localhost:7777 # Default credentials # > User : `admin` # > Password : `password` # Edit API definition code -r ./models/api-v1.yaml # Created entries and uploaded medias + variations # are stored in root project by default in `.data` tree ./.data
or… with Docker Compose ?
cd ./docker make rdc-std - # Data persistence folder tree ./docker/std/.volume/.data
Makefile for all containers variants and shorthands.
Some views ?
Auto-generated forms from OpenAPI definitions
JSON Schema validation on run-time for both client and server sides
UI Schema augmentation (non-standard)
Settings are splitted in two different schemas at runtime. Standard compliant JSON Schema alongside non standard UI Schema.
JSON files database
All your textual data is hosted unded
./data/docs (root can be overriden with
Run multiple instances of Paper CMS easily by setting different
Quickly swip datasets : demo / tests / staging / production…
Image(s) upload + dynamic resize while fetching + caching
JWT authentication for both human editors and API consumers
Full live reload for models / client / server
When editing model definitions, server or client code, everything is re-runned/builded/bundled. Also, browser is automatically refreshed thanks to a long polling web socket.
You can also trigger browser refresh by hitting
Document revisions history
Soft deletion, restore from trash
“Has many” relationship via references
for full examples.
Nested referenced documents editing
A “sub” document is just another document reference.
There is no hierarchy or inheritance,
only cross-references betweens entities.
While you can create, edit or associate an existing document from the main document form,
$refs URI for child references actually gets recorded, not the entire subtree.
Everything can be a document collection, as soon as it make sense to reference the entity from elsewhere. Self-sufficient data should live embedded in the document itself.
There is no limit for nesting, though stacked modal editors force us to save only one (sub)document at a time: no full tree update propagation. This design choice is meant to prevent data-loss / infinite recursive nesting.
Schema.org inspired default definitions
While Schema.org states that:
The type hierarchy presented on this site is not intended to be a ‘global ontology’ of the world.
While true, it provides a great starting point with commonly used taxonomies and entities relationships. Schema.org is shining for content-driven web sites where SEO is crucial (but that’s just an excuse). While still in its infancy, JSON/LD is already bringing HATEOS concepts into real-life applications, step-by-step, organically. Regardless, feature-rich widgets are democratizing, and data crawling between third-parties is becoming more insightful.
OpenAPI 3 UI (Swagger)
The endgoal is to make Paper CMS a non-deterministic data ingestion / organization / retrieval
At the end, an hypermedia API should be auto-discoverable.
Still, it’s useful to rely on Swagger niceties for on-boarding an API.
Moreover, the OpenAPI 3 specs is adding
links, a notable concept for Hypermedia minded APIs.
Wysiwyg HTML Editor
under the hood. Basic additional HTML sanitization is done server-side.
Custom fields and widgets
We are seeing the emergence of different patterns in the content management world like:
- Shared entities vocabularies
- Automatic web form generation
- Isomorphic user input runtime validation,
- Entity / Collection oriented information architecture
- Headless non-opinionated CMS APIs for JAMStack consumption
- Hypermedia for non-deterministic data fetching via refs. | links | URIs…
- Plain files data storage for operations convenience (with some trade-offs)
- Conventions over configuration, with extendabilities (models, widgets…)
All these concepts are explored at different levels of implementations in Paper CMS. While it’s still an experiment, the end-goal is to provide a lightweight solution suitable for projects which:
- Has ten-ish max. editors in charge
- Needs moderate authoring concurrency with silo-ed document edits
- Might needs frequent content updates
- Low needs for user-land data input
- Are in an eco-system of focused services where caching / CDNs / whatever are dedicated
To sum up: Paper CMS is good for editors-driven web sites, but is not a good fit for users-driven web apps.
ℹ️ Project insights
⚠️ Work in progress: NOT FOR PRODUCTION ⚠️
Mono-repo. glued with PNPM recursive modules installation.
- React Quill
- JSON Schema React
Work in progress
- Single media management
- Batch media management
- JSON/LD API output conformance
- OpenAPI conformance
- Swagger integration
- Wider Schema.org support for stock definitions
- Basic users account management
- Media metadata with EXIF + IPTC support
- API collections’ pagination
- Automatic bi-directional relationships (“Is part of many” <=> “Has many”)
- Custom data fetching and population widgets for APIs / social networks content retrieval
- Might propose fully dynamic OpenAPI GUI builder right inside the back office, instead OR alongside YAML config.
- Might propose MongoDB/pSQL/S3 alternative to bare file storage, for increased mass and/or concurrency needs, but decreased portability.
- Might propose an option for storing media binaries in an S3 bucket.
,ggggggggggg, dP""88""""""Y8, Yb, 88 `8b `" 88 ,8P 88aaaad8P" 88""""",gggg,gg gg,gggg, ,ggg, ,gggggg, 88 dP" "Y8I I8P" "Yb i8" "8i dP""""8I 88 i8' ,8I I8' ,8i I8, ,8I ,8' 8I 88 ,d8, ,d8b,,I8 _ ,d8' `YbadP' ,dP Y8, 88 P"Y8888P"`Y8PI8 YY88888P888P"Y8888P `Y8 I8 I8 ,gggg, ,ggg, ,ggg,_,ggg, ,gg, I8 ,88"""Y8b,dP""Y8dP""Y88P""Y8b i8""8i I8 d8" `Y8Yb, `88' `88' `88 `8,,8' I8 d8' 8b d8 `" 88 88 88 `88' I8 ,8I "Y88P' 88 88 88 dP"8, I8' 88 88 88 dP' `8a d8 88 88 88 dP' `Yb Y8, 88 88 88 _ ,dP' I8 `Yba,,_____, 88 88 Y8,"888,,____,dP `"Y8888888 88 88 `Y8a8P"Y88888P"