@akasha-platform/vendure-craftjs
v0.0.3
Published
A set of hooks and components to provide components that interact with vendure and can be integrated into craftjs.
Downloads
2
Readme
vendure.craft.js
Overview
@akasha-platform/vendure-craftjs
is part of a set of open source repositories which together can be setup to serve a flexible content and ecommerce framework based on microservices/-frontends architecture.
The use of vendure.io as an e-commerce and GraphQL backend and craft.js with a set of customized components has the potential to serve as a solid but flexible interface between merchants/content creators and their customers/target audience.
What is vendure.io?
vendure.io is "A modern, headless GraphQL-based e-commerce framework built with TypeScript & Nodejs"
Its small footprint, easy customisation, extendability and microservice oriented architecture make vendure a perfect candidate for a modern content/e-commerce platform.
What is craft.js?
craft.js is " a React framework for building powerful & feature-rich drag-n-drop page editors."
With craft.js it is possible to fairly quickly build up customised drag and drop page builders as it servers only as a page building framework and lifts off the burden of handling editor state, history and drag and drop handling from you shoulders.
It is possible to build simple React Components with an additional few lines of code to make them compatible with craft.js, however we will see later that the @akasha-platform/craftjs-tool
library takes care of a lot of the setup for us.
How do the two work together?
Since both, craft.js and vendure.io do not work together out of the box, a set of repositories was created to make this marriage possible. The microservices are the following:
- Shop API (Customer facing GraphQL API)
- Admin API (Admin facing GraphQL API)
- Admin UI (Admin facing UI)
- Shopfrontend (Customer facing UI)
- Page Editor (Admin facing publishing UI)
In order to make this work both, craft.js and vendure.io need to be extended to support the funtionalities required by @akasha-platform/vendure-craftjs
.
On the backend side the @akasha-platform/vendure-document-plugin
is used to provide an admin facing GraphQL API for managing page trees, meta-data and publishing criteria.
On the frontend side we need to tell craft.js how to fetch page contents and render components using @akasha-platform/craftjs-tools
and @akasha-platform/vendure-craftjs
.
Setup
This documentation will show you how to setup vendure.io, install all requirements, setup a craft.js page builder and how to extend both the customer facing UI and the admin facing UI (some parts of the vendure admin UI will not be covered).
Project setup
The final project will have the following folder strucure.
example-project/
|-- vendure/
| |-- package.json
| |-- ...
|
|-- page-builder/
| |-- package.json
| |-- ...
|
|-- shop-front/
| |-- package.json
| |-- ...
Installation (Admin facing)
Vendure
Install Vendure
yarn create @vendure vendure
When it asks for the database you're using, select SQLLite for simplicity. If you want to use other database engines you will have to make sure that they are up and reachable for the installation process.
Select Typescript as your programming language and select the rest as you desire.
Configure Vendure
yarn add @akasha-platform/vendure-document-plugin
// vendure-config.ts
import { DocumentPlugin } from "@akasha-platform/vendure-document-plugin";
export const config = {
/*...*/
plugins: [/*...*/ DocumentPlugin],
};
and then simply run
yarn migration:generate document-plugin
yarn migration:run document-plugin
This should be enough to have the backend setup. Now start the development environment and check if everything went ok by running
yarn start
If everything went fine, you should be able to login into the shop backend via http://localhost:3000/admin/login
Page Builder
Back in our main project folder we are ready to create our page builder application. You might need to install install-peerdeps for convenience.
Install Page Builder
yarn create react-app page-builder --template typescript
cd ./page-builder
install-peerdeps @akasha-platform/vendure-craftjs
After using install-peerdeps
you might want to rearrange some of the packages in the dependencies
section of your package.json
files to devDependencies
and don't forget to re-run yarn install
.
Configure Page Builder
In order to actually use the Page Builder we will have to implement a redux store and an apollo client for use by the components delivered with @akasha-platform/vendure-craftjs
.
First we will create our redux store:
// ./src/store.ts
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { exportedUserComponentsReducer } from "@akasha-platform/craftjs-tools";
import { navigationReducer } from "@akasha-platform/vendure-craftjs";
const reducer = combineReducers({
exportedComponents: exportedUserComponentsReducer,
navigation: navigationReducer,
});
const store = configureStore({
reducer,
});
export type RootState = ReturnType<typeof store.getState>;
export default store;
And now our clients:
// ./src/client.ts
import {
ApolloClient,
ApolloLink,
createHttpLink,
from,
InMemoryCache,
} from "@apollo/client";
import { onError } from "@apollo/client/link/error";
const AUTH_TOKEN = "vendure-auth-token";
const middlewareAuthLink = new ApolloLink((operation, forward) => {
const token = localStorage.getItem(AUTH_TOKEN);
const authorizationHeader = token ? `Bearer ${token}` : null;
operation.setContext({
headers: {
authorization: authorizationHeader,
},
});
return forward(operation);
});
const afterwareLink = new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
const context = operation.getContext();
const {
response: { headers },
} = context;
if (headers) {
const refreshToken = headers.get("vendure-auth-token");
if (refreshToken) {
localStorage.setItem(AUTH_TOKEN, refreshToken);
}
}
return response;
});
});
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
export const adminClient = new ApolloClient({
link: from([
errorLink,
middlewareAuthLink,
afterwareLink,
createHttpLink({
uri: "http://localhost:3000/admin-api",
}),
]),
cache: new InMemoryCache(),
});
export const frontendClient = new ApolloClient({
link: from([
errorLink,
middlewareAuthLink,
afterwareLink,
createHttpLink({
uri: "http://localhost:3000/shop-api",
}),
]),
cache: new InMemoryCache(),
});
Last but not least we setup our App.tsx
to show the craft.js editor.
To use a react-redux
provider we will have to install it first:
// ./src/App.tsx
import { muiTheme, Resolver } from "@akasha-platform/craftjs-tools";
import {
AppEditor,
LoginBox,
vendureUserComponents,
} from "@akasha-platform/vendure-craftjs";
import { ApolloProvider } from "@apollo/client";
import { Frame } from "@craftjs/core";
import { MuiThemeProvider } from "@material-ui/core";
import React, { useEffect, useState } from "react";
import { Provider } from "react-redux";
import { adminClient, AUTH_TOKEN, frontendClient } from "./client";
import store from "./store";
export const App = () => {
const resolver = new Resolver({
...vendureUserComponents,
});
resolver.resolve();
const [token, setToken] = useState(localStorage.getItem(AUTH_TOKEN));
useEffect(() => {
function updateToken() {
setToken(localStorage.getItem(AUTH_TOKEN));
}
window.addEventListener("storage", updateToken);
return () => {
window.removeEventListener("storage", updateToken);
};
}, [setToken]);
return (
<>
{token ? (
<AppEditor
store={store}
adminClient={adminClient}
frontendClient={frontendClient}
resolver={resolver}
editMode={true}
>
<Frame>{resolver.create("ContentArea")}</Frame>
</AppEditor>
) : (
<Provider store={store}>
<ApolloProvider client={adminClient}>
<MuiThemeProvider theme={muiTheme}>
<LoginBox />
</MuiThemeProvider>
</ApolloProvider>
</Provider>
)}
</>
);
};
export default App;
After running
yarn start
We should be able to start the editor now and directly start to use it.