Building Extensions for

Calypso & WordPress.com

Kevin Killingsworth

https://github.com/coderkevin

@coderkevin

Follow along:  http://bit.do/quest-for-calypso

  • WooCommerce
  • Calypso as a Framework
  • The wp-admin experience
  • Calypso Extensions

The Quest for Calypso

Calypso Framework

+

He’s just got two bits of code and he’s banging them together!

The Quest:

Bring Calypso to WooCommerce

https://github.com/Automattic/wc-synchrotron

// package.json

{
…

  "devDependencies": {
    …
    "wp-calypso": "github:automattic/wp-calypso#cafb19f51804ad683c3e852cbaa187654f24529e"
  }
}

i18n

CSS Naming

// package.json


  "scripts": {
    …

    "build-synchrotron-strings":

"node_modules/wp-calypso/server/i18n/bin/i18n-cli.js
 dist/synchrotron-strings.php
 synchrotron_i18n_strings
 dist/synchrotron_bundle.js",

    "makepot": "grunt dev"
  }
// assets/stylesheets/style.scss



.uses-s9n-styles {
  // Shared
  @import 'shared/reset'; // css reset before the rest of the styles are defined
  @import 'shared/functions'; // functions that we've used from Compass, ported over
  @import 'shared/functions/functions'; // sass functions for z-index, etc.

  …
}

The Black Knight of Webpack

module: {
  loaders: [
    {
      test: /\.jsx?$/,
      include: [
        path.resolve( __dirname, 'client' ),
        path.resolve( __dirname, 'node_modules', 'wp-calypso', 'client' )
      ]
    }
    …
}

resolve: {
  extensions: [ '', '.js', '.jsx', '.json', '.scss', '.html' ],
  modulesDirectories: [ 'node_modules' ],
  root: [
    path.join( __dirname, 'client' ),
    path.join( __dirname, 'node_modules', 'wp-calypso', 'client' )
  ]
},
sassLoader: {
  includePaths: [
    path.resolve( __dirname, 'node_modules', 'wp-calypso', 'client' ),
    path.resolve( __dirname, 'node_modules', 'wp-calypso', 'assets', 'stylesheets' )
  ]
},

The Killer Rabbit of NPM



    - node_modules
      - react
      - wp-calypso
        - node_modules
          - react
"calypso-delete-redundancies": "rimraf node_modules/wp-calypso/node_modules/react",

Framework:

Try a definitive plugin pattern

PR #8103

An initial exploration of what extensions/plugins may look like...

Skilled Calypso Devs

Jetpack!

Sending requests to WP REST API of the Jetpack site

You can send requests to the WP REST API of any site that has Jetpack 4.5 or newer, and is connected to WordPress.com for the current user. Requests are sent to a special WordPress.com endpoint, which proxies the request, signs it and safely dispatches it to the remote site, returning the output from the remote endpoint.

The New Quest:

Bring WooCommerce to Calypso

“Stop! Who would cross the Bridge of Calypso must answer me these questions three, ere the other side he see.”

https://github.com/Automattic/wp-calypso

“I blow my nose at your extra whitespace!”

“Your mother was a sloppy coder, and your father smelt of space indenting!”

“Now fix your formatting, or I will taunt you a second time!"

React

Redux

Calypso Framework

Use Component State!

Single State Tree!

First, use Flux, then use Redux

Black Knight

of Webpack

Returns!

function generateReducerRequireString( extensionDir ) {
  return `'${ camelCase( extensionDir ) }': require( 'extensions/${ extensionDir }/state/reducer' )`;
}

function generateExtensionsModuleString( reducerRequires ) {
  return `module.exports = {
    reducers: function() {
      return {
        ${ reducerRequires.join( ',\n' ) }
      };
    }
  };`;
}

Unit Tests are Important

"I like what you did with the exports particularly. But there is one small problem..."

// client/state/data-layer/extensions-middleware.js

const configuration = configureMiddleware( {}, {} );

export function configureMiddleware( handlers, config = configuration ) {
  config.handlers = handlers;
  config.middleware = buildMiddleware( handlers );
  return config;
}

Add new extension

- client
  - extensions
    - woocommerce
      - package.json
      - index.js
// package.json

{
  "name": "woocommerce",
  "author": "Automattic",
  "description": "WooCommerce Store",
  "version": "0.0.1",
  "env_id": [ "development", "wpcalypso" ],
  "section": {
    "name": "woocommerce",
    "paths": [ "/store" ],
    "module": "woocommerce",
    "group": "sites",
    "secondary": true
  }
}

Add new extension

Hooking up to React

// index.js

renderWithReduxStore(
  React.createElement( ProductCreate, { } ),
  document.getElementById( 'primary' ),
  context.store
);

Add new extension

Hooking up to React

Hooking up to Redux

// state/reducer.js

export default combineReducers( {
	ui,
	wcApi,
} );

Add new extension

Hooking up to React

Hooking up to Redux

Adding URL Routes

// index.js

export default function() {
  if ( config.isEnabled( 'woocommerce/extension' ) ) {
    page( '/store/:site?', siteSelection, navigation, Controller.dashboard );
    page( '/store/:site?/products/add', siteSelection, navigation, Controller.addProduct );
  }
}

Add new extension

Hooking up to React

Hooking up to Redux

Adding URL Routes

WP REST API (via Jetpack)

 

// state/wc-api/product-categories/actions.js
// In action creator...

  return wp.req.get( { path: jpPath }, { path: apiPath } )
    .then( ( { data } ) => {
      dispatch( fetchProductCategoriesSuccess( siteId, data ) );
    } )
    .catch( err => {
      dispatch( error( siteId, getAction, err ) );
    } );

Add new extension

Hooking up to React

Hooking up to Redux

Adding URL Routes

WP REST API (via Jetpack)

i18n

// app/product/product-form-details-card.js

import i18n from 'i18n-calypso';

// In React Component class...
render() {
  const { product, translate } = this.props;

  return (
    <Card className="products__product-form-details">
      <FormLabel>{ translate( 'Featured' ) }</FormLabel>
    </Card>
  );
}

Add new extension

Hooking up to React

Hooking up to Redux

Adding URL Routes

WP REST API (via Jetpack)

i18n

Dependencies on WP Plugins

Dependencies on other Extensions

Upgrade path/version control

Capabilities are present, but constantly evolving.

Questions?

The Quest for Calypso

By Kevin Killingsworth

The Quest for Calypso

  • 1,872