diff --git a/asciidoc/blueprints/blueprints.adoc b/asciidoc/blueprints/blueprints.adoc new file mode 100644 index 000000000000..f9ce26eb18b6 --- /dev/null +++ b/asciidoc/blueprints/blueprints.adoc @@ -0,0 +1,11 @@ += Blueprints + +== What are blueprints? + +Blueprints are a quick way to build something cool on Koji. Each blueprint includes a simple, block-by-block guide and an “as-built” code sample for a fun Koji application. + +These blueprints are intended for developers who prefer to jump straight to code. For a step-by-step intro to Koji, head to the link:/developer/getting-started[starter guide]. + +== Build your application + +* link:/developer/magazine-cover[Magazine cover] - Add customizable images and text to put your own picture and headline on a magazine. diff --git a/asciidoc/blueprints/magazineCover.adoc b/asciidoc/blueprints/magazineCover.adoc new file mode 100644 index 000000000000..c50158b9d714 --- /dev/null +++ b/asciidoc/blueprints/magazineCover.adoc @@ -0,0 +1,192 @@ += Magazine Cover Template +:description: Add customizable images and text to put your own picture and headline on a magazine. +:imagesdir: ../images/ + +== Summary +[#img-overview] +image::magazine-cover.png[Make a magazine cover template on Koji] + +Follow this blueprint to build a template for your own picture and headline on a magazine cover. You will add customizable images and text, and then publish the template on Koji. + +=== Prerequisites + +* Familiarity with web development. React and ES6 basics are a plus. +* Familiarity with the Koji remix process. For an overview, see the link:/developer/getting-started[starter guide]. + +=== Level + +* *Koji*: Beginner – Intermediate +* *Developer*: Intermediate – Advanced +* *Time*: 45 minutes + +== Building blocks + +=== Remix the scaffold + +Remix an existing web application on Koji that implements basic elements of your favorite framework. + +link:++https://withkoji.com/~seane/simple-react-scaffold++[https://withkoji.com/~seane/simple-react-scaffold] + +=== Install the packages + +Install @withkoji/vcc to expose Visual Customization Controls (VCCs), dynamically update custom values, and display your template correctly in the Koji feed. + +[source,bash] +---- +npm install --save @withkoji/vcc +---- + +=== Create the customization files + +Create `.koji/customization/settings.json` to define customizable values for the magazine name, cover image, background color, and text options (text, size, color, and position). + +[source,json] +---- +include::../codeSamples/magazineCoverSettings.json[] +---- + +Remove the unused customization files. + +`colors.json`, `images.json`, and `strings.json` + +=== Add the template logic + +Import the packages. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=importPackages] +---- + +Use `InstantRemixing` to get and set custom values. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=instantRemixing] +---- + +Use `FeedSdk` to display the template in the Koji feed. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=feedSdk] +---- + +Monitor the remix state. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=monitorRemix] +---- + +Dynamically get and set custom values. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=updateValues] +---- + +Optimize the user's cover image. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=optimizeImage] +---- + +Add click handlers for editable elements. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=clickHandlers] +---- + +Use dynamic sizing to support different browsers and devices. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=dynamicSizing] +---- + +Indicate the template is ready for instant remixes and to display in the feed. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=templateReady] +---- + +Render the template with custom values. Apply conditional styling to editable elements during remix. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=renderTemplate] +---- + +Render a view to use as the rich preview image when the template is shared on social media. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=renderSocial] +---- + +=== Add the styles + +Define styles for the template, including the headline, cover image. Define styles for the rich preview image. Remove unused styles. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=styles] +---- + +Add styles for editable elements during remix. + +[source,css] +---- +.editable { + border: 2px dashed grey; +} +---- + +Add the font stylesheet. + +[source,html] +---- + +---- + +=== Add entitlements + +Create `.koji/project/entitlements.json` and enable instant remix support and listing in the Koji feed. + +[source,json] +---- +include::../codeSamples/entitlements.json[] +---- + +=== Test + +Use the tools in the Koji editor to test template functionality. For example: + +* Template default view: *Refresh* the *Live preview* tab. +* Conditional styling of editable elements: In the live preview, switch between *Preview* and *Editing* mode. +* VCC targeting: In *Editing* mode, click each editable element. The corresponding VCC should open. +* Remix functionality: In the JSON file, switch to *Visual* view, and use VCC editor to customize values. The template should update immediately. +* Template styles on another browser or device: On the *Remote* tab, copy the URL or use the QR code to open a link to the staging server. + +=== Publish + +Click *Publish Now* and enter a *Name* (defines the permalink URL to your template), *Description* (displays along with your template on Koji), and other publish settings, as desired. Then, click *Publish*. + +When publishing is completed, click the link in the message to view your live template on Koji. Your template is now available to remix and share anywhere on the web. You can create a fun version for yourself and share it on your favorite site to see what your friends make. + +== "As Built" sample code + +To see this blueprint as a completed template on Koji, visit the following link. From there, you can view the source code or remix the template into your own project. + +https://withkoji.com/~RachelSienko06/blueprint-magazine-cover[Blueprint: Magazine Cover] + +The following code is a completed sample of the template logic described in this blueprint. + +[source,javascript] +---- +include::../codeSamples/magazineCoverReact.js[tags=**] +---- diff --git a/asciidoc/codeSamples/entitlements.json b/asciidoc/codeSamples/entitlements.json new file mode 100644 index 000000000000..4a1ac2c57e38 --- /dev/null +++ b/asciidoc/codeSamples/entitlements.json @@ -0,0 +1,6 @@ +{ + "entitlements": { + "InstantRemixing": true, + "FeedEvents": true + } +} diff --git a/asciidoc/codeSamples/magazineCoverReact.js b/asciidoc/codeSamples/magazineCoverReact.js new file mode 100644 index 000000000000..9ea056776e3a --- /dev/null +++ b/asciidoc/codeSamples/magazineCoverReact.js @@ -0,0 +1,213 @@ +import React, { useEffect, useRef, useState } from "react"; +import styled from "styled-components"; +//tag::importPackages[] +import { FeedSdk, InstantRemixing } from "@withkoji/vcc"; +//end::importPackages[] + +//tag::styles[] +const Wrapper = styled.div` + background-color: ${({ style: { bgColor } }) => bgColor}; + height: 100vh; + width: 100vw; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; +`; + +const MagazineCover = styled.div` + width: ${({ style: { width } }) => width}px; + height: ${({ style: { height } }) => height}px; + top: ${({ style: { top } }) => top}px; + left: ${({ style: { left } }) => left}px; + background: url("${({ style: { backgroundImage } }) => + backgroundImage}") no-repeat center center / cover; + position: absolute; + z-index: 0; +`; + +const Magazine = styled.img` + max-height: 100%; + max-width: 100%; + z-index: 1; + pointer-events: none; +`; + +const H1 = styled.div` + position: absolute; + top: ${({ y }) => `${y}%`}; + left: ${({ x }) => `${x}%`}; + font-family: "Roboto", sans-serif; + color: ${({ color }) => color}; + font-size: ${({ fontSize }) => `${fontSize}px`}; + max-width: 35%; + cursor: default; +`; + +const SocialSharePreview = styled.div` + background-color: ${({ style: { bgColor } }) => bgColor}; + height: 630px; + width: 1200px; + position: absolute; + top: 0; + left: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; +`; +//end::styles[] + +//tag::optimizeImage[] +const optimizeURL = url => + `${url}?fit=bounds&width=${window.innerWidth - + 15}&height=${window.innerHeight - 15}&optimize=medium`; +//end::optimizeImage[] + +//tag::instantRemixing[] +const instantRemixing = new InstantRemixing(); +//end::instantRemixing[] +//tag::feedSdk[] +const feed = new FeedSdk(); +//end::feedSdk[] + +const App = () => { + // Handle remixing state + //tag::monitorRemix[] + const [isRemixing, setIsRemixing] = useState(instantRemixing.isRemixing); + useEffect(() => { + instantRemixing.onSetRemixing(isNowRemixing => { + setIsRemixing(isNowRemixing); + }); + }, []); + //end::monitorRemix[] + + //Handle value updates + //tag::updateValues[] + const [magazineName, setMagazineName] = useState( + instantRemixing.get(["settings", "magazineName"]) + ); + const [coverImage, setCoverImage] = useState( + instantRemixing.get(["settings", "coverImage"]) + ); + const [bgColor, setBgColor] = useState( + instantRemixing.get(["settings", "bgColor"]) + ); + const [textOptions, setTextOptions] = useState( + instantRemixing.get(["settings", "textOptions"]) + ); + + useEffect(() => { + instantRemixing.onValueChanged(([scope = "", key = ""], value) => { + if (scope === "settings" && key === "magazineName") + setMagazineName(value); + if (scope === "settings" && key === "coverImage") setCoverImage(value); + if (scope === "settings" && key === "bgColor") setBgColor(value); + if (scope === "settings" && key === "textOptions") setTextOptions(value); + }); + }, []); + //end::updateValues[] + + //Click handlers for remixing + //tag::clickHandlers[] + const handleClick = e => { + if (e.target.closest(".text")) { + instantRemixing.onPresentControl(["settings", "textOptions"]); + } else { + instantRemixing.onPresentControl(["settings"]); + } + }; + //end::clickHandlers[] + + //tag::dynamicSizing[] + // Handle dynamic resizing + const [size, setSize] = useState({}); + + // Set a reference for the magazine div (import useRef from React to follow this pattern) + const magazineRef = useRef(null); + + // Set dynamic size properties for the cover image + const runSetSize = () => { + setSize({ + height: magazineRef.current.height, + width: magazineRef.current.width, + top: magazineRef.current.offsetTop, + left: magazineRef.current.offsetLeft + }); + }; + + // Re-run the set sizing function when the window is resized + useEffect(() => { + window.addEventListener("resize", runSetSize); + return () => window.removeEventListener("resize", runSetSize); + }, []); + //end::dynamicSizing[] + + //tag::templateReady[] + useEffect(() => { + // Wrap in the final useEffect so it's sure to run after anything else + instantRemixing.ready(); + feed.load(); + }, []); + //end::templateReady[] + + //tag::renderSocial[] + if (window.location.search.includes("koji-screenshot=1")) { + return ( + + + {size.height && ( + +

+ {textOptions.title} +

+
+ )} +
+ ); + } + //end::renderSocial[] + + return ( + //tag::renderTemplate[] + + + {size.height && ( + +

+ {textOptions.title} +

+
+ )} +
+ //end::renderTemplate[] + ); +}; + +export default App; diff --git a/asciidoc/codeSamples/magazineCoverSettings.json b/asciidoc/codeSamples/magazineCoverSettings.json new file mode 100644 index 000000000000..f29f3cd15ad1 --- /dev/null +++ b/asciidoc/codeSamples/magazineCoverSettings.json @@ -0,0 +1,95 @@ +{ + "settings": { + "magazineName": "https://images.koji-cdn.com/38587b11-db1e-4e64-b099-a63e22f3666c/nfakd-2.png", + "coverImage": "https://images.koji-cdn.com/14c02947-0b36-4b2b-ace3-6d205bb84e3b/tl7ta-download20200602T105158.824.png", + "bgColor": "#f7e8a2", + "textOptions": { + "title": "The greatest ever...", + "fontSize": 15, + "color": "#592efb", + "position": { + "x": 2, + "y": 30 + } + }, + "background": "#be47f9" + }, + "@@editor": [ + { + "key": "settings", + "name": "App settings", + "icon": "⚙️", + "source": "settings.json", + "fields": [ + { + "key": "magazineName", + "name": "Magazine name", + "type": "select", + "typeOptions": { + "placeholder": "Choose a magazine...", + "options": [ + { + "value": "https://images.koji-cdn.com/5eaaf00f-c8bb-46ba-8de2-96c41a44d93a/w44bz-Cosmofix.png", + "label": "Cosmopolitan" + }, + { + "value": "https://images.koji-cdn.com/48a8b044-5695-4bf0-8726-6f6d1a09b69e/usir2-BrowserPreview_tmp.png", + "label": "Forbes" + }, + { + "value": "https://images.koji-cdn.com/23ac8d20-2619-43ce-80f9-0e085e72dc8d/yznns-01.png", + "label": "AARP" + }, + { + "value": "https://images.koji-cdn.com/38587b11-db1e-4e64-b099-a63e22f3666c/nfakd-2.png", + "label": "GQ" + } + ] + } + }, + { + "key": "coverImage", + "name": "Cover image", + "type": "image" + }, + { + "key": "bgColor", + "name": "Background Color", + "type": "color" + }, + { + "key": "textOptions", + "name": "Text options", + "type": "object", + "typeOptions": { + "TextOption": { + "title": { + "name": "Headline", + "description": "Headline for your cover image", + "type": "text" + }, + "fontSize": { + "name": "Text size", + "description": "Select a size for the title font", + "type": "range", + "typeOptions": { + "min": 4, + "max": 30, + "step": 1 + } + }, + "color": { + "name": "Color", + "type": "color" + }, + "position": { + "name": "Text position", + "type": "coordinate" + } + } + } + } + ] + } + ] +} diff --git a/asciidoc/gettingStarted/developer.adoc b/asciidoc/gettingStarted/developer.adoc new file mode 100644 index 000000000000..f7ea94253f7b --- /dev/null +++ b/asciidoc/gettingStarted/developer.adoc @@ -0,0 +1,49 @@ += Koji Developer Portal + +== About Koji + +Koji is a platform that enables anyone, including non-techies, to +quickly create interactive content, such as selfies, memes, games, and +utilities. Kojis can be shared via a link on social media and messengers +as well as in an embedded iframe on a website. + +As a developer, you can build web applications on Koji, called +“templates,” that enable users to customize, or “remix,” them without +coding. At their core, Koji templates are embeddable, mini-web +applications written in modern JavaScript. They are designed to be +responsive, so that they can run on any browser and every device. They +also enable non-technical users to quickly edit elements, such as +images, text, and sounds, to create a custom version that they can share +anywhere on the web. + +On Koji, you can develop templates that will be used and shared by +millions of users across the world. You can also monetize your work +through licensing, asset packs, and other developer compensation +programs. With the ability to create and share remixable, interactive +content, the opportunities for creative new applications and experiences +are countless. We can’t wait to see what YOU make! + +image:../images/Koji-developer.svg[Overview of the Koji development +process,title="Koji development process"] + +== Getting Started + +For some great resources to help you start developing templates on Koji, +see: + +* link:../gettingStarted/startGuide1.adoc[Starter guide] – +Step-by-step instructions on how to create a remixable web application +and publish it as a template on Koji. +* https://withkoji.com/developer/getting-started-course[Starter course] – Video +tutorial of how to start developing applications on Koji. + +== Staying in Touch + +Join the https://discord.gg/eQuMJF6[Koji community] on Discord to +connect with other developers, makers, and the Koji team. The community +is the best place to share tips and tricks, provide peer feedback, and +get support. + +Subscribe to the http://eepurl.com/g5odab[developer email list] to keep +up with the latest announcements, featured content, events, and +developer programs. diff --git a/asciidoc/gettingStarted/startGuide1.adoc b/asciidoc/gettingStarted/startGuide1.adoc new file mode 100644 index 000000000000..131981a95078 --- /dev/null +++ b/asciidoc/gettingStarted/startGuide1.adoc @@ -0,0 +1,375 @@ += Developing your first Koji template + +== Summary + +On the Koji platform, you can develop JavaScript web applications that can be customized without coding. Instead, non-technical users can use Visual Customization Controls (VCCs) to quickly edit elements of the application, such as images, text, and sounds. + +In this starter guide, you will start with an existing web +application on Koji, called a “template,” and add the ability to customize, or “remix,” it. You will use the Koji editor and an npm package from Koji to define the customizable elements. Then, you will publish your application as a new template so that Koji users can create their own customized versions of it. + +== Remixing the starter template + +. If you haven’t already, create an account at https://withkoji.com[withkoji.com]. +. Go to https://withkoji.com/templates/seane/react-project-no-vccs[https://withkoji.com/templates/seane/react-project-no-vccs]. +. Click *Create Remix*. ++ +This action creates a clone of the starter template, and opens it in the Koji editor. +. Explore the template and the Koji editor. +* In the right pane, you can see a live preview of the template. +* In the left pane, you can click *Source Code* to expand the file browser. From here, you can open and edit your project files in the editor. +* At the bottom, you can expand a set of terminal tabs. These tabs enable you to run the template locally from inside the editor and to execute other terminal functions, such as adding packages and committing changes. ++ +NOTE: If you make changes to your project’s structure (by adding npm packages, for example), you might need to exit the running process and restart the development server in the `frontend` terminal. + +== Installing the @withkoji/vcc package + +The @withkoji/vcc package allows your template to access dynamic values that are stored in customization files. It also allows you to expose VCCs so that a user can change the customizable items in your template. Finally, it provides a watcher function that allows you to monitor changes to customization files and perform a real-time set of the dynamic values stored in the customization files. + +. In the terminal, navigate to the `frontend` folder of your template. +. Cancel the running process (for example, press *Ctrl+C*). +. Install the latest version of the package: +[source, bash] +npm install --save @withkoji/vcc +. In the `frontend` folder of your project, reconfigure the +`package.json` file to run the watcher concurrently with your +development server. You can use a package like npm-run-all. For example: ++ +[source,JavaScript] +---- +"build": "NODE_ENV=production webpack --config ./.internals/webpack.production.js --color -p --progress --hide-modules --display-optimization-bailout", +"start": "npm-run-all -p watch start:server", +"watch": "koji-vcc watch", +"start:server": "node index.js" <1> +---- +<1> Replace with the "start" command for your project ++ +[NOTE] +==== +If you follow the example pattern, you must also install the npm-run-all package: +[source,bash] +npm install --save-dev npm-run-all +==== + +. Restart the process to reflect the new changes: +[source, bash] +npm start + +## Creating a customization file + +A customization file is a JSON file that defines the names and types of the customizable values in a template, so that Koji can display the appropriate VCCs for remixers. + +. In the `.koji/customization` folder of your project, create a new JSON file. +.. In the file browser, click the plus (*+*) next to the `.koji/customization` folder, and click *New File*. +.. Enter a name for the file. For example: `settings.json`. +. Paste the following code into your `settings.json` file. ++ +This code defines a scope and the customizable values within that scope. ++ +[source, json] +---- +{ + "settings": { + "title": "Hello World!" +}, +"@@editor": [ + { + "key": "settings", + "name": "App settings", + "icon": "⚙️", + "source": "settings.json", + "fields": [ + { + "key": "title", + "name": "App title", + "type": "text" + } + ] + } + ] + } +---- +. Press *Ctrl-S* to save the file. ++ +A new item appears in the *Customization* section of the left pane. +. Click the item in the *Customization* section to display the associated VCC in the editor. ++ +In this example, the file stores one customizable value (`settings.title`), and Koji displays a text VCC to collect this value from a remixer. + +== Accessing the values stored in a customization file + +To access a value from a JSON customization file within a template, you use a getter from the @withkoji/vcc package. Then, update the template to use dynamic values, instead of hard-coded values. + +. From the left pane of the editor, open the `frontend/common/App.js` file. ++ +This file contains most of the template logic. +. At the top of the file, import the package. ++ +[source,JavaScript] +---- +import { InstantRemixing } from '@withkoji/vcc'; +---- +. In the React component, add the `componentDidMount` method. ++ +This method creates a new instance of the `InstantRemixing` class to use in the template. ++ +[source,JavaScript] +---- +componentDidMount() { +this.instantRemixing = new InstantRemixing(); +console.log('instantRemixing', this.instantRemixing); // Confirm w/log + +// Alert Koji we are ready to use instantRemixing +this.instantRemixing.ready(); +} +---- +. Create a state to handle updates to the title (`h1`) value, and update the contents of the `h1` element to use the dynamic value. ++ +[source,JavaScript] +---- +class App extends React.Component { + state = { + title: '', +}; + +... + +render() { + return ( + +

{this.state.title}

+ +
+); +} +} +---- + +. In the `componentDidMount` method, use the getter function from `instantRemixing` to get the default value from the customization file. ++ +The getter accepts an array (`[scope, key]`) that maps to the scope (`settings`) and key (`title`) from the JSON customization file. ++ +[source,JavaScript] +---- +componentDidMount() { + this.instantRemixing = new InstantRemixing(); + + // Set the default value + this.setState({ + title: this.instantRemixing.get(['settings', 'title']) + }); + + // Alert Koji we are ready to use instantRemixing + this.instantRemixing.ready(); +} +---- + +== Reacting to updated values + +When a remixer enters a new value, the template must update automatically to reflect the change. + +* In the `componentDidMount` method, set up a listener to monitor for changes to the template value: ++ +[source,JavaScript] +---- + +componentDidMount() { + this.instantRemixing = new InstantRemixing(); + +// Alert Koji we are ready to use instantRemixing +this.instantRemixing.ready(); + +// Set the default value +this.setState({ + title: this.instantRemixing.get(['settings', 'title']) +}); + +// Set up a listener to update title value +this.instantRemixing.onValueChanged((path, newValue) => { + if (path[0] && path[1] && path[0] === 'settings' && path[1] === 'title') { + this.setState({ title: newValue }); + } +}); +} +---- + +## Testing the current state of the template + +At this point, the template should be configured to use the default value from the customization file and to react to value changes that are made from VCCs. To test this configuration, you can use the built-in VCC and live preview in the Koji editor. + +1. In the top right of the *Live Preview* pane, click *Refresh* to make sure you are seeing the latest version. +2. From the left pane of the editor, click *Customization > App Settings* to open the VCC for the `settings.json` customization file. +3. In the VCC, update the value in the *App title* field. ++ +The preview window should reflect your update automatically. + +## Determining the current view of the template + +The template must display differently and expose different click handlers depending on whether a user is viewing or customizing the template. In this example, you will add styles to show that the `h1` element is editable and a click handler to expose a VCC when a user is customizing the template. + +. Create a property (`isRemixing`) to track the current view state, and set the initial state with a placeholder value. ++ +[source, JavaScript] +---- +state = { + isRemixing: false, + title: '', +}; +---- + +. In the `componentDidMount` method, add the default value (`this.instantRemixing.isRemixing`) to the `setState` function, and add a listener that monitors the template for view changes. ++ +This listener allows you to use `this.state.isRemixing` as a source of truth for the current view of the template. ++ +[source,JavaScript] +---- +componentDidMount() { +this.instantRemixing = new InstantRemixing(); + +// Set the default value for title and isRemixing state +this.setState({ + isRemixing: this.instantRemixing.isRemixing, + title: this.instantRemixing.get(['settings', 'title']) +}); + + // Set up a listener to update title value +this.instantRemixing.onValueChanged((path, newValue) => { + if (path[0] && path[1] && path[0] === 'settings' && path[1] === 'title') { + this.setState({ title: newValue }); + } +}); + +// Toggle the isRemixing state based on the listener +this.instantRemixing.onSetRemixing((isRemixing) => { + this.setState({ isRemixing }); +}); + +// Alert Koji we are ready to use instantRemixing +this.instantRemixing.ready(); +} +---- + +== Exposing the VCC + +The template must expose a way for a remixer to open the VCC when customizing it. + +* Add a click handler to the `h1` element that opens the VCC when the remixer clicks the title. ++ +[source,JavaScript] +---- +handleClick = () => { + // Conditionally handle the click, only if the template is being remixed +if (this.state.isRemixing) { +this.instantRemixing.onPresentControl(['settings', 'title']); +} +}; + +render() { + return ( + +

{this.state.title}

+ +
+ ); +} +---- + +## Testing the expose function + +To test whether the expose function is working, you can use the *Editing* tab of the *Live Preview* pane. This feature enables you to test the template as if it were published on Koji. + +1. In the *Live Preview* pane, click *Editing* to switch to the template editing mode. +2. Click the title in the preview. ++ +The VCC should open automatically and allow for text input. If this test works correctly, the VCC should be exposed correctly to the remixer in your published template. + +## Styling the customizable item + +To indicate that an item is “editable,” you can add a conditional visual effect that is displayed when the template is being customized. In this example, you’ll add a CSS style class for editable items and then apply the class to the `h1` when a user is customizing the template. + +. From the left pane of the editor, open the `frontend/common/index.html` file. +. Add the following CSS style in the `head` element. ++ +[source,HTML] +---- + +---- ++ +. In the `App.js` file, update the `h1` element with a dynamic `className`. ++ +[source,JavaScript] +---- +

+ {this.state.title} +

+---- + +. To test the dynamic `className`, you can toggle the live preview between the *Editing* and *Preview* modes. +* In *Editing* mode, the “editable” styles should be visible, and the click handler should open the VCC, as expected. +* In *Preview* mode, the “editable” styles should not be visible, and nothing should happen when clicking the `h1` element. + +== Making the template “feed-aware” + +Koji uses a feed to enable users to browse available templates. As with traditional social feeds, items move from off screen or out of focus, into the main window inside the feed. To ensure the template is displayed correctly in the Koji feed, you use the FeedSdk from the @withkoji/vcc package to set the template state and handle transitions between on and off screen and in and out of focus. + +. Import the `FeedSdk` from the @withkoji/vcc package. ++ +[source,JavaScript] +---- +import { FeedSdk, InstantRemixing } from '@withkoji/vcc'; +---- +. At the end of the `componentDidMount` method, add the following code to display the template in the feed. ++ +This code creates an instance of the feed and calls a load function to indicate that the template is ready to be displayed in the feed, which is all that is required when the template does not use autoplay. ++ +[source,JavaScript] +---- +this.feed = new FeedSdk(); +this.feed.load(); +---- +NOTE: If you plan to develop apps that autoplay when focused in the feed, you can use the `onPlaybackStateChanged` listener to monitor for real-time updates as the template enters and leaves focus in the feed, similar to how this example uses `onSetRemixing`. + +## Adding entitlements for the Koji profiler + +When you publish the template, it is submitted into a queue for profiling. The Koji profiler checks for errors and generates metadata about the application. If the template is error-free, the profiler enables additional platform features for your template, including the instant remix option and inclusion in the feed. To prepare your template to be profiled correctly, you must add entitlements for some of these features. + +* In the `.koji/project` folder, create an `entitlements.json` file with the following code: ++ +[source, JSON] +---- +include::../codeSamples/entitlements.json[] +---- +This code indicates that the template supports remixes and is ready to be listed in the feed. + +== Publishing the template + +At this point, the template is ready to be published. + +. To view the template on the staging server before you publish it, click the *Remote* tab in the right pane, and then use one of the options to open a preview in another tab or on another device. +. In the upper left of the editor, click *Publish Now* to open the publish settings. +. Give your template a unique name and add a description. ++ +NOTE: The permalink URL to your template is based on the name when you first publish it, so be sure to enter the name you want to use going forward. You can republish it to update any template functionality and settings, but the link remains the same. + +. Click *Publish*. ++ +A message appears to indicate that the publishing process has started. +When publishing is completed, a link appears in the message. +. Click the link to view and test your live template. ++ +The template might be published before profiling is completed. +Therefore, you might need to wait longer before testing features that require profiling, such as inclusion in the feed or the ability to instantly remix the template. To see the results of the most recent profiling, from your live template, click *Make your own > Fork template* to open the template welcome screen. Then, under *More options*, click *See profiled attributes*. ++ +If an error message appears when you open the link after profiling is completed, you can review the steps in this guide to fix it. To open your project again, go to *Koji home > My projects*, and click the template name. diff --git a/asciidoc/images/Koji-developer.svg b/asciidoc/images/Koji-developer.svg new file mode 100644 index 000000000000..1b8a1796b47a --- /dev/null +++ b/asciidoc/images/Koji-developer.svg @@ -0,0 +1,3 @@ + + +
Develop
Develop
Share
Share
Koji Template (Scaffold)
Koji Template...
 Existing Code (Outside Koji)
Existing Code...
Import
Import
Remix / Fork
Remix / Fork
Koji Project / Editor
Koji Project / Edi...
Publish
Publish
Share
Share
Remix / Fork (Developer)
Remix / Fork...
Instant Remix (User)
Instant Remix...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/asciidoc/images/magazine-cover.png b/asciidoc/images/magazine-cover.png new file mode 100644 index 000000000000..c61959c3e367 Binary files /dev/null and b/asciidoc/images/magazine-cover.png differ diff --git a/images/Koji-developer.svg b/images/Koji-developer.svg deleted file mode 100644 index 75488b7e4b54..000000000000 --- a/images/Koji-developer.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -
Develop
Develop
Share
Share
Koji Template (Scaffold)
Koji Template...
 Existing Code (Outside Koji)
Existing Code...
Import
Import
Remix / Fork
Remix / Fork
Koji Project / Editor
Koji Project / Edi...
Publish
Publish
Share
Share
Remix / Fork (Developer)
Remix / Fork...
Instant Remix (User)
Instant Remix...
Viewer does not support full SVG 1.1
\ No newline at end of file