Creating a Custom Decentralised Renderer
TradeTrust documents are both readable by machines as well as by humans. Every TradeTrust document file is stored in a .json
format, allowing any application to process the content within. To present the data file in a human-readable format, a renderer needs to be written.
In this guide, we will build and deploy the renderer to display data from a 📜 Certificate of Completion.
This renderer is a static website that will be embedded in compliant TradeTrust viewer. It will take in the TradeTrust document and generates the corresponding HTML code for rendering.
Prerequisites​
Clone Decentralized Renderer React Template​
A template for building your own document renderer has been created for you at our GitHub template repository.
Clone code repository locally​
git clone https://github.com/TradeTrust/tradetrust-decentralized-renderer.git
cd tradetrust-decentralized-renderer
rm -rf .git
Install code dependencies​
npm install
Run development preview​
npm run storybook
Development environment​
After running the Storybook, you should be able to see the templates samples provided at http://localhost:6006/
.
This is a live preview where you can see the changes when you:
- edit the raw document data in the
Knobs
tab - edit the template code to render the data
Clean the template​
In order to fully understand how developing a renderer work, we will start by cleaning it a bit:
- remove all the template folders under
src/templates
don't delete src/templates/index.tsx
as it is the template registry
=======
Once you have finished the tutorial feel free to clone the repository again and have a look into the deleted files.
Once you have a better understanding about how this decentralised renderer works, you can go ahead and fork a version of this repo and start development of your very own decentralised renderer template.
Developing the Document Renderer​
Now that we have set up the development environment, we can start writing our document renderer. We will first define the data structure of our 📜 Certificate of Completion (COC), followed by writing the renderer to render the HTML code corresponding to the data provided.
Update sample document data and type​
To update the raw document data and the corresponding data type, you will need to create the new folder for the template and data definition file in src/templates/coc/sample.ts
:
import { v2 } from "@trustvc/trustvc";
export interface CocTemplateCertificate extends v2.OpenAttestationDocument {
name: string;
recipient: {
name: string;
};
}
export const cocTemplateCertificate: CocTemplateCertificate = {
name: "TradeTrust Tutorial Certificate of Completion",
issuers: [
{
name: "My name",
documentStore: "0xBBb55Bd1D709955241CAaCb327A765e2b6D69c8b",
identityProof: {
location: "few-green-cat.sandbox.openattestation.com",
type: v2.IdentityProofType.DNSTxt,
},
},
],
recipient: {
name: "John Doe",
},
$template: {
name: "COC",
type: v2.TemplateType.EmbeddedRenderer,
url: "http://localhost:3000",
},
};
Document objects explained​
In the above TradeTrust document, you will see four root objects:
$template
​
The $template
key to describe the template name used to render this display. It should have the following keys:
-
$template.name
is the name of the template used to render a given TradeTrust document. This allows a single document renderer to render for multiple types of TradeTrust documents; each with a different template name. -
$template.type
will always take the value ofEMBEDDED_RENDERER
for documents rendered in this manner. -
$template.url
will be the remote URL where your TradeTrust decentralized renderer resides. For now, we set it tohttps://localhost:3000
but we will change this value later on in the Deploying Document Renderer section.
name
​
The name
key is a compulsory key to describe the type of TradeTrust document. In this case, we are creating a TradeTrust Tutorial Certificate of Completion
.
recipient
​
TradeTrust documents do not have a strict data structure and allows issuers of documents to define their own data schema. The recipient
object is a user-defined object that describes who the certificate is conferred to. In this case, you may replace John Doe
with your name.
In the next section, you will learn more about the TradeTrust document schema and how you may define your own data structure. For this guide, we will stick to this simple document.
issuers
​
Developing the COC Template View​
Now that the structure of the data has been defined, we may proceed to style our 📜 Certificate of Completion.
To change how the data is being rendered, we simply create a React component that takes in the raw document in the document
props and render the corresponding HTML code.
For our 📜 Certificate of Completion, we will simply display the following text:
OpenAttestation Tutorial Certificate of Completion
awarded to
John Doe
The first step consist of creating a file src/templates/coc/template.tsx
with the following content:
import React, { FunctionComponent } from "react";
import { TemplateProps } from "@tradetrust-tt/decentralized-renderer-react-components";
import { css } from "@emotion/core";
import { CocTemplateCertificate } from "./sample";
const containerStyle = css`
background-color: #324353;
color: #ffffff;
padding: 15px;
margin: auto;
width: 80%;
text-align: center;
`;
export const CocTemplate: FunctionComponent<TemplateProps<CocTemplateCertificate> & { className?: string }> = ({
document,
className = "",
}) => {
return (
<div css={containerStyle} className={className} id="custom-template">
<h1>{document.name}</h1>
<div>awarded to</div>
<h2>{document.recipient.name}</h2>
</div>
);
};
Now that the component has been created, we can add a story to view it. Next to src/templates/coc/template.tsx
create a file called template.stories.tsx
with the following content:
import { Meta, Preview, Props, Description, Story } from "@storybook/addon-docs/blocks";
import { CocTemplate } from "./template";
import { cocTemplateCertificate } from "./sample";
import { FunctionComponent } from "react";
import React from 'react';
export default {
title: "Sample Template",
component: CocTemplate,
parameters: {
componentSubtitle: "Sample Template",
},
};
export const SampleTemplate: FunctionComponent = () => {
return <CocTemplate document={cocTemplateCertificate} handleObfuscation={() => {}} />;
};
We can now [start storybook](#run-development-preview) and make sure our component looks like expected as below.
![Completed Story Book View](/docs/reference/configuration/custom-renderer/completed-storybook.png)
### Certificate of Completion template configuration
A TradeTrust document may have multiple views, each of them rendered in separate tabs. For example, a TradeTrust document that is a degree certificate may have the actual certificate as one view, and the transcript as another view in a single template.
For our 📜 Certificate of Completion, we will only use a single view. Create a file `src/templates/coc/index.tsx` with the following content:
```js
import { CocTemplate } from "./template";
export const templates = [
{
id: "certificate",
label: "Certificate",
template: CocTemplate,
},
];
templates
must be an array where each element correspond to a view (or a tab). Here we need only one view.- Each view must define the following property:
id
which must be a uniq identifier for this template configuration.label
which will be displayed by tab in the application loading the renderer.template
which is is the component that will be displayed.
Renderer template configuration​
src/templates/index.tsx
is a file containing the configuration of all the templates available in this renderer.
To register a new template, simply add it as a key to the registry
constant. Take note that the key is case sensitive and must match the $template.name
value defined in the document data.
Replace src/templates/index.tsx
with the following code to add the new COC
template:
import { TemplateRegistry } from "@tradetrust-tt/decentralized-renderer-react-components";
import { templates } from "./coc";
export const registry: TemplateRegistry<any> = {
COC: templates,
};
If you open src/index.tsx
you will notice that the registry
defined above is used and provided to a component called FramedDocumentRenderer
. This component will handle automatically the connection to the application and will display the correct component depending on your configuration. You can find more information in this github repository
Now, your document renderer is ready to be built and deployed online.
Deploying Document Renderer​
Push code to GitHub​
Create a new repository in GitHub and push the code to the new repository. For a step-by-step guide to import source code to GitHub, you may read this guide.
Deploy site onto Netlify​
Once you have your code on GitHub, you may build and deploy the site onto Netlify.
Select "New Site From Git" and then "GitHub".
On the build page, enter npm run build
as the "Build command" and dist
as the "Publish Directory" and click on "Deploy Site".
Once the site has been deployed, you will obtain the URL to the document renderer site. In the above example, the URL is https://frosty-joliot-c02c3d.netlify.com/
.
Note that the website will be an empty page when viewed directly. This is normal because it is not meant to be viewed directly through a web browser.
Save the website url for future reference. You should also update the
$template.url
in your OA document.
Additional Note for Production Document Renderer​
It is recommended to use a custom domain you own for the document renderer website in production. This prevents locking in to any specific third party hosting provider.
If you are using Netlify, we recommend you to check out how to enable custom domains.
Decentralized Renderer Core Components​
Decentralized renderer core components, located in the src/core directory
, are reusable React components that offer enhanced functionalities for your decentralized renderer template. We recommend you to check out using decentralized renderer core components