ssr social-network handlebars REST API single-page-app WordPress API components pop decentralization Content Management System PWA Framework GraphQL PHP
Need help with PoP?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.
leoloso

Description

Description of an architecture based on a server-side component model

131 Stars 20 Forks MIT License 599 Commits 5 Opened issues

Services available

Need anything else?

PoP

PoP

This repo contains only documentation concerning the component-model architecture. All actual code (and their corresponding documentation) is found on all the different repositories under the PoP organization account.

Description

PoP describes an architecture based on a server-side component model. It has been implemented in PHP, but can also be considered a mental model for building applications in any language.

PoP is components all the way down. Each component is implemented partly in the back-end, and partly in the front-end. The component-based architecture provides the mechanism to build, configure and even deploy the application (eg: by providing support for the serverless paradigm).

In PoP, everything is a module

CMS-agnostic, based on contracts

PoP relies on contracts to interact with the underlying CMS or framework, where all logic resides. As such, it is CMS-agnostic, and it can work with any PHP-based CMS or framework (WordPress, Symfony, Laravel, Joomla, Drupal).

So far only the contracts for WordPress have been implemented, but extending it to any other platform is very simple: Only all the repos ending on

"-wp"
, which contain the implementation of the contracts for WordPress, need be re-implemented.

No creeping business logic

PoP doesn't implement any business logic, and doesn't attempt to re-invent the wheel: Authentication, CRUD operations, validation, etc are all implemented by the CMS; PoP is simply a layer which makes use of all this already-existing functionality, and makes it easily available to the application.

Design goals

PoP's architecture attempts to achieve the following goals:

✅ High level of modularity:

  • Strict top-down module hierarchy: Ancestor modules know their descendants, but not the other way around
  • One-way setting of props across modules, from ancestors to descendants
  • Configuration values are set through an API instead of through the application

✅ Minimal effort to produced a maximum output:

  • Isomorphism of code
  • Output for different applications (website, mobile app, emails, etc)

✅ Maintainable/Easy to debug and fix:

  • Modules are focused on a single task or goal

✅ Aggressive caching, implemented across several layers:

  • Server-side caching
  • HTTP caching
  • Asset caching and, in addition, content-caching through CDN, service workers and local storage in client

✅ Deployable on serverless PHP

  • Server-side components are the perfect mechanism to execute atomic operations on a serverless environment

✅ Self documentation:

  • Component pattern libraries are automatically generated by rendering each module on their own

Install

Follow the instructions in:

(Other projects coming soon...) <!-- - PoP API for Laravel + WordPress (coming soon) - PoP site for WordPress (coming soon) -->

Architecture foundations

The architecture establishes the following foundations:

  1. Everything is a module (also called component)
  2. The module is its own API <!--
  3. The API and the application use the same code --> 1. Everything is a module

A PoP application contains a top-most module (also called a component) which wraps other modules, which themselves wrap other modules, and so on until reaching the last level:

Sequence of modules wrapping modules wrapping modules, from an avatar all the way up to the webpage

Hence, in PoP everything is a module, and the top-most module represents the page.

2. The module is its own API

Every module, at whichever level inside the component hierarchy (i.e. the composition of modules starting from the top-most, all the way down to the last level), is independently accessible simply by passing along its module path in the URL:

/page-url/?output=json&modulefilter=modulepaths&modulepaths[]=path-to-the-module
<!-- 3. The API and the application use the same code

In PoP, the application consumes its data from itself. Indeed, the application and the API are the same entity, so there is no code duplication whatsoever (eg: for user authentication). Moreover, the application can consume the data already on the server-side, avoiding the extra latency from consuming data on the client-side. -->

Progressive/Resilient components

In most libraries/frameworks in the market, the implementation of the concept of components is based on JavaScript. In PoP, a component has a progressive approach, and its implementation spans from back to front-end:

Back-end Front-end
Component hierarchy
Data loading
Configuration
Props
Styles
View
Reactivity

Response specification

The output from requesting a URL can contain several layers: At its core it is a data layer (enough for implementing an API), which can be further extended by a configuration layer (to implement a website).

1. Data layer

The data layer represents data in the following way:

  • Database data is retrieved through a relational structure under section
    databases
  • The IDs which are the results for each component are indicated through entry
    dbobjectids
    (under section
    datasetmoduledata
    )
  • Where to find those results in the database is indicated through entry
    dbkeys
    (under section
    modulesettings
    )
  • All database data is normalized (i.e. not repeated)

The API response looks like this:

{
  databases: {
    primary: {
      posts: {
        1: {
          author: 7, 
          comments: [88]
        },
        2: {
          recommendedby: [5], 
          comments: [23]
        },
      },
      users: {
        5: {
          name: "Leo"
        },
        7: {
          name: "Pedro"
        },
        18: {
          name: "Romualdo"
        }
      },
      comments: {
        23: {
          author: 7, 
          post_id: 2, 
          content: "Great stuff!"
        },
        88: {
          author: 18, 
          post_id: 1, 
          content: "I love this!"
        }
      }
    }
  },
  datasetmoduledata: {
    "topmodule": {
      modules: {
        "datamodule1": {
          dbobjectids: [1], 
        },
        "datamodule2": {
          dbobjectids: [2], 
        }
      }
    }
  },
  modulesettings: {
    "topmodule": {
      modules: {
        "datamodule1": {
          dbkeys: {
            id: "posts",
            author: "users",
            comments: "comments"
          }
        },
        "datamodule2": {
          dbkeys: {
            id: "posts",
            recommendedby: "users",
            comments: "comments"
          }
        }
      }
    }
  }
}

2. Configuration layer

The configuration layer can provide those properties and values required to build any kind of application:

{
  modulesettings: {
    "topmodule": {
      modules: {
        "layoutpostmodule": {
          configuration: {
            class: "text-center"
          },
          modules: {
            "titlemodule": {
              configuration: {
                class: "title bg-info",
                htmltag: "h3"
              }
            },
            "postcontentmodule": {
              configuration: {
                maxheight: "400px"
              },
              modules: {
                "authoravatarmodule": {
                  configuration: {
                    class: "img-thumbnail",
                    maxwidth: "50px"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Success stories

PoP is the foundation for the GraphQL API for PoP, an exceptional implementation of GraphQL which supports features not typically supported in GraphQL: HTTP caching, composable fields, composable directives, linear complexity time to resolve queries, and native federation and decentralization, among others.

In the near future, PoP will enable to build websites and export them as static. <!--

Use cases for PoP

Among others, PoP is suitable for the following applications:

👉🏽 As an API

The PoP API can combine the best of both GraphQL and REST in a single API: no under or over-fetching or data while supporting server-side cache and not being open to DoS attacks. Through extension GraphQL API the application becomes a GraphQL server, and through extension REST API the application can add custom REST endpoints.

👉🏽 As a hybrid dynamic/static website (currently not available)

By using javascript templates, components can be rendered into HTML, as to produce the website. By pre-rendering the components, the website can be partly exported as static. Then, the application is a hybrid: While the dynamic part of the site is handled from the server, the static sections can be served from a CDN.

👉🏽 To be deployed on serverless PHP

Components are the perfect mechanism to execute atomic operations on a serverless environment. For instance, WordPress can't run on serverless. However, a standalone component, deployed on serverless, can access the data from the WordPress database and render it for the visitors.

👉🏽 To execute any type of operation supported by the CMS

PoP is CMS-agnostic, and can run on top of any CMS and be a proxy to execute its functionality (retrieve data, post data, log the user in, send an email, etc). It is extremely simple to set-up and use: PoP exposes a single URL-based interface to execute the whole functionality. <!--

👉🏽 Homogenize the architecture of the application

The component-based architecture acts as the foundation for the overall application, including accessing data through the API, and implementation of its many features (many of them already provided out of the box, such as code splitting, A/B testing, client-side state management and layout cache).

👉🏽 Maximize the output from a small team

The architectural single source of truth makes it possible to produce HTML for the server-side, client-side, transactional emails, and any other desired output, and power more than one application (for instance, a website + a mobile app), allowing a single developer to handle all these tasks.

👉🏽 To produce component stylesheets

Component pattern libraries can be automatically generated by rendering each component on its own. <!--

👉🏽 Robust architecture based on splitting a component's responsibilities into server and client-side

Using components as the building unit of a website has many advantages over other methods, such as through templates. Modern frameworks bring the magic of components to the client-side for functionality (such as JavaScript libraries React and Vue) and for styles through component pattern libraries (such as Bootstrap). PoP splits a component's responsibilities into server-side (props, configuration, other) and client-side (view, reactivity), creating a more resilient and robust architecture.

Documentation

Alongside the code, each repository on the PoP organization account contains its corresponding technical documentation, in its README file.

Currently, most of the technical documentation is found on these repositories:

Articles concerning PoP

The following articles concern how different features in PoP were implemented:

🔗 Intro to PoP API, a new GraphQL server in PHP: Description of how the GraphQL API for PoP compares against a typical GraphQL

🔗 Demonstrating the PoP API, an implementation of GraphQL on steroids: Step-by-step description of solving a complex use case using the GraphQL API for PoP

🔗 Abstracting WordPress Code To Reuse With Other CMSs: Concepts (Part 1) and Implementation (Part 2): Design and implementation of strategies to make PoP become CMS-agnostic

🔗 “Create Once, Publish Everywhere” with WordPress: How through the WordPress editor Gutenberg” a PoP application can export data to be consumed in different mediums or platforms (website, app, emails, etc)

🔗 Introducing the Component-based API: Article describing all the main concepts of the PoP architecture

🔗 Caching Smartly In The Age Of Gutenberg: Caching mechanism implemented in PoP, allowing to cache pages even when the user is logged-in (to be emulated for Gutenberg)

🔗 Avoiding The Pitfalls Of Automatically Inlined Code: How PoP generates JS/CSS resources to improve performance

🔗 Sending Emails Asynchronously Through AWS SES: Mechanism to send emails through AWS SES implemented for PoP

🔗 Adding Code-Splitting Capabilities To A WordPress Website Through PoP: How PoP implements code-splitting of JavaScript files

🔗 How To Make A Dynamic Website Become Static Through A Content CDN: Mechanism implemented for PoP to route dynamic content through a CDN to improve performance

🔗 Implementing A Service Worker For Single-Page App WordPress Sites: The strategy behind the creation of the service-worker.js file in PoP (when running under WordPress), which powers its offline-first caching strategy

🔥 Become involved!

Contributors are welcome! Please check PoP in PHP to see what we need help with. If either you want to get involved, or simply find out more about PoP, simply send Leo an email or tweet 😀❤️.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.