# Add a Configuration MFE in App Builder
Entando MFEs can be customized through an App Builder feature that uses a specialized micro frontend. This tutorial splits the process into 4 steps:
- Modify an existing MFE (the target MFE) to take a configuration option
- Create a new MFE (the config MFE) to provide a user interface for the configuration option
- Set up the target MFE to use the configuration provided by the config MFE
- Publish and test the configurable MFE
# Prerequisites
# Step 1: Add a Configuration Option to a Target MFE
Start by adding a configuration option to an existing MFE. If you don't already have one, you can create it via the React MFE tutorial.
# Add an Attribute to the Custom Element
- Replace the contents of src/custom-elements/WidgetElement.jswith the following code to add attribute handling to the custom element and re-render the app when an attribute changes. This enables the Entando-providedconfigto be passed as a property to the React root component (App).
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from '../App';
const ATTRIBUTES = {
    config: 'config'
};
class WidgetElement extends HTMLElement {
    static get observedAttributes() {
        return Object.values(ATTRIBUTES);
    }
    connectedCallback() {
        this.mountPoint = document.createElement('div');
        this.appendChild(this.mountPoint);
        this.root = createRoot(this.mountPoint);
        this.render();
    }
    attributeChangedCallback(attribute, oldValue, newValue) {
        if (!WidgetElement.observedAttributes.includes(attribute)) {
            throw new Error(`Untracked changed attributes: ${attribute}`)
        }
        if (this.mountPoint && newValue !== oldValue) {
            this.render();
        }
    }
    render() {
        const attributeConfig = this.getAttribute(ATTRIBUTES.config);
        const config = attributeConfig && JSON.parse(attributeConfig);
        this.root.render(
            <App config={config} />
        );
    }
}
customElements.define('simple-mfe', WidgetElement);
- Replace the contents of src/App.jswith the following. This component now receives theconfigproperty and displays thenameparameter it contains. This turns the static component from the React MFE tutorial into a more dynamic component.
import './App.css';
function App({config}) {
  const { params } = config || {};
  const { name } = params || {};
  return (
      <div className="App">
        <header className="App-header">
          <p>
            Hello, {name}!
          </p>
        </header>
      </div>
  );
}
export default App;
- For test purposes, add a configuration file public/mfe-config.jsonwith the following content:
{
    "params": {
        "name": "Jane Smith"
    }
}
- Replace the bodyofpublic/index.htmlwith the following. This allows you to set the MFEconfigattribute and test locally with the same configuration structure provided by Entando.
<simple-mfe/>
<script>
   function injectConfigIntoMfe() {
     fetch('%PUBLIC_URL%/mfe-config.json').then(async response => {
       const config = await response.text()
       const mfeEl = document.getElementsByTagName('simple-mfe')[0]
       mfeEl.setAttribute('config', config)
     })
   }
   
   injectConfigIntoMfe()
</script>
- Start the app and confirm that "Hello, Jane Smith!" is displayed. Use Ctrl+C to close the app.
ent bundle run simple-mfe
# Step 2: Create a Config MFE
Next, create a new MFE for managing the configuration option. These steps are very similar to the React MFE tutorial.
- Add a new microfrontend to your bundle project:
ent bundle mfe add simple-mfe-config --type=widget-config
- Generate a new React app:
npx create-react-app microfrontends/simple-mfe-config --use-npm
- Start the app:
ent bundle run simple-mfe-config
- Create a microfrontends/simple-mfe-config/src/WidgetElement.jscomponent with the following content to set up the custom element for the config MFE.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
class WidgetElement extends HTMLElement {
   constructor() {
      super();
      this.reactRootRef = React.createRef();
      this.mountPoint = null;
   }
   get config() {
      return this.reactRootRef.current ? this.reactRootRef.current.state : {};
   }
   set config(value) {
      return this.reactRootRef.current.setState(value);
   }
   connectedCallback() {
      this.mountPoint = document.createElement('div');
      this.appendChild(this.mountPoint);
      this.render();
   }
   render() {
      ReactDOM.render(<App ref={this.reactRootRef} />, this.mountPoint);
   }
}
customElements.define('simple-mfe-config', WidgetElement);
App Builder integration
- A config MFE must retain its state in a configproperty
- The App Builder supplies the configproperty when the config MFE is rendered
- When a user saves the form, the App Builder automatically persists the configuration through Entando APIs
- Replace the contents of src/App.jswith the following to add a simple form for managing a singlenamefield
import React, {Component} from 'react';
class App extends Component {
   constructor(props) {
      super(props);
      this.state = {
         name: props.name
      };
   }
   handleChange = e => {
      const input = e.target;
      this.setState({
         [input.name]: input.value,
      });
   };
   render() {
      const { name } = this.state;
      return (
        <div>
           <h1>Simple MFE Configuration</h1>
           <div>
              <label htmlFor="name">Name </label>
              <input id="name" name="name" defaultValue={name} type="text" onChange={this.handleChange}  />
           </div>
        </div>
      );
   }
}
export default App;
TIP
- When the config MFE is displayed within the App Builder, the App Builder styles will be applied.
- Replace the contents of src/index.jswith the following:
import './index.css';
import './WidgetElement';
- For test purposes, add a configuration file microfrontends/simple-mfe-config/public/mfe-config.jsonwith the following content. Note: the JSON for a config MFE contains just parameters so it is simpler than the JSON for a target MFE.
{
  "name": "John Brown"
}
- Replace the bodyofpublic/index.htmlwith the following. This allows you to set the config MFE parameters and test locally.
<simple-mfe-config/>
<script>
   function injectConfigIntoMfe() {
     fetch('%PUBLIC_URL%/mfe-config.json').then(async response => {
       const config = await response.json()
       const mfeEl = document.getElementsByTagName('simple-mfe-config')[0]
       mfeEl.config = config
     })
   }
   
   injectConfigIntoMfe()
</script>
# Step 3: Configure the Target MFE to Use the Config MFE
- Edit the entando.jsonand add these properties to thesimple-mfein order to connect the config MFE to this target MFE and specify the available params.
"configMfe": "simple-mfe-config",
"params": [
    {
        "name": "name",
        "description": "The name for Hello World"
    }
]
# Step 4: Publish and Test the Configurable MFE
- Build and install the bundle with the following commands. For more details, see the Build and Publish tutorial. - ent bundle pack- ent bundle publish- ent bundle deploy- ent bundle install
- Test the full setup by adding the widget into an existing page. The config MFE should be displayed when the widget is first added to the page. 
- Fill out the - namefield and click- Save. You can update the widget configuration at any point by clicking- Settingsfrom the widget actions in the Page Designer.
- Publish the page and confirm the target MFE is configured and displays correctly.