<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Aniket</title>
    <description>The latest articles on Forem by Aniket (@aniketchanana).</description>
    <link>https://forem.com/aniketchanana</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F507257%2F743c3498-a2a3-4268-8387-f436cb3ef4ac.jpeg</url>
      <title>Forem: Aniket</title>
      <link>https://forem.com/aniketchanana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aniketchanana"/>
    <language>en</language>
    <item>
      <title>Structuring our Node.JS application</title>
      <dc:creator>Aniket</dc:creator>
      <pubDate>Mon, 01 Jan 2024 08:42:53 +0000</pubDate>
      <link>https://forem.com/aniketchanana/structuring-our-nodejs-application-2hho</link>
      <guid>https://forem.com/aniketchanana/structuring-our-nodejs-application-2hho</guid>
      <description>&lt;p&gt;In this segment we will be discussing how node applications can be structured using clean architecture principles, with the help of a Todo application (&lt;a href="https://github.com/aniketchanana/clean-architecture-node.js"&gt;github repo link&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;To make it easier let’s walk through every single layer from the module of the application to acknowledge the core concepts.&lt;/p&gt;

&lt;p&gt;We will be using MongoDB, Node, TypeScript, express and &lt;a href="https://inversify.io/"&gt;inversify&lt;/a&gt; to create the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Inversify?
&lt;/h2&gt;

&lt;p&gt;With the help of inversify you can automate your dependancy injection, instead of every time passing dependancy manually you can create a container and with the help of TS decorators you can easily pass dependancy into your objects, here is example of passing dependancy with and without inversify&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;with inversify&lt;/strong&gt; 👇&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ITodoService {...}  

@injectable()  
class TodoService implements ITodoService {  
  @inject(Types.Todo\_REPOSITORY)  
  private todoRepository: ITodoRepository;  
  ...  
}  

interface ITodoRepository {...}  
@injectable()  
class TodoRepository implements ITodoRepository {  
  @inject(Types.ToDo\_TABLE)  
  private todoTable: TodoAppDataSource&amp;lt;ITodoModel\&amp;gt;;  
  ...  
}  


export interface ITodoController {...}  

@injectable()  
class TodoController implements ITodoController {  
  @inject(Types.Todo\_SERVICE)  
  private todoService: ITodoService;  
  ...  
}  

// using todo controller  
const todoController = dIContainer.get&amp;lt;ITodoController\&amp;gt;(Types.Todo\_CONTROLLER);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;without inversify&lt;/strong&gt; 👇&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface ITodoService {...}  

class TodoService implements ITodoService {  
  constructor(private todoRepository: ITodoRepository) {...}  
  ...  
}  

interface ITodoRepository {...}  

class TodoRepository implements ITodoRepository {  
  constructor(private todoTable: TodoAppDataSource&amp;lt;ITodoModel&amp;gt;) {...}  
  ...  
}  

export interface ITodoController {...}  

class TodoController implements ITodoController {  
  constructor(private todoService: ITodoService) {...}  
  ...  
}  

// using todo controller  
const todoController = new TodoController(new TodoService(new TodoRepository()))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So you can see from both the example how inversify makes our life easy without inversify every time you want to create instance of TodoController you have to manually pass other 2 dependancies which can be a tedious task as your application grows larger, so it is better to use inversify or some other DI automation tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application layers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9rltu0mE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:770/1%2A6ygcA97ezJgLZGUCF7XY9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9rltu0mE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:770/1%2A6ygcA97ezJgLZGUCF7XY9w.png" alt="" width="385" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Diagram representing our app structure&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Js-rfsMV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1132/1%2AMSyvpge8CulnUpx_hOS6yw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Js-rfsMV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:1132/1%2AMSyvpge8CulnUpx_hOS6yw.png" alt="" width="566" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sample file structure&lt;/p&gt;

&lt;p&gt;Our application is divided into 5 layers, here is the detailed explanation of each layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1 (Routes)
&lt;/h2&gt;

&lt;p&gt;Routes is the inner most layer because it is very rare that you will change any route name so it will be the core of application.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function TodoRoutes() {  
  const router = express.Router();  
  const todoController = dIContainer.get&amp;lt;ITodoController&amp;gt;(  
    Types.Todo\_CONTROLLER  
  );  

  router  
    .route("/")  
    .post(todoController.createNewTodo)  
    .get(todoController.getAllTodo)  
    .patch(todoController.updateTodo)  
    .delete(todoController.deleteTodo);  

  return router;  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here if you see the only responsibility of this layer is to register routes and redirect incoming request to its respective controller.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2 (Controller)
&lt;/h2&gt;

&lt;p&gt;Controller is responsible for&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Handling incoming request.&lt;/li&gt;
&lt;li&gt; Validating request body.&lt;/li&gt;
&lt;li&gt; Sending response to client.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Below example you see our TodoController is dependant on our TodoService and it implements ITodoService interface so that means all classes that implements ITodoService interface is eligible to be injected in TodoController and this can be used for swapping business logic, it just have to implement ITodoService interface and thats it our TodoController doesn’t needs to know anything about TodoService it will simply adapt with the type of object passed in it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@injectable()
export class TodoController implements ITodoController {  
@inject(Types.Todo_SERVICE)  

private todoService: ITodoService;  

public createNewTodo = async (req: AuthenticatedRequest, res: Response) =&amp;gt; {...};



public getAllTodo = async (  
    req: AuthenticatedRequest,  
    res: Response  
): Promise&amp;lt;Response\&amp;gt; =&amp;gt; {...};  
public updateTodo = async (req: AuthenticatedRequest, res: Response) =&amp;gt; {...};  
  public deleteTodo = async (req: AuthenticatedRequest, res: Response) =&amp;gt; {...};
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Layer 3 (Service)
&lt;/h2&gt;

&lt;p&gt;Service is our 3rd layer which is responsible of handling our business logic, it is dependant on TodoRepository and any class which satisfy the interface ITodoRepository can be injected in TodoService.&lt;/p&gt;
&lt;h2&gt;
  
  
  Layer 4 (Repository)
&lt;/h2&gt;

&lt;p&gt;At number 4 we have repository which is responsible of any kind of outer world connection whether it calling any external service API or talking to database all such things are handled in this layer.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@injectable()  
class TodoRepository implements ITodoRepository {  
  @inject(Types.ToDo\_TABLE)  
  private todoTable: TodoAppDataSource&amp;lt;ITodoModel\&amp;gt;;  

  private getParameterObj = (  
    content: string,  
    userId: string  
  ): Omit&amp;lt;ITodoModel, "\_id"\&amp;gt; =&amp;gt; ({  
    ...  
  });  

  createNewEntry = async (  
    content: string,  
    userId: string  
  ): Promise&amp;lt;ITodoModel\&amp;gt; =&amp;gt; { ... };  

  getAllUserTodo = async (userId: string) =&amp;gt; { ... };  

  deleteTodo = async (  
    userId: string,   
    todoId: string  
  ): Promise&amp;lt;ITodoModel\&amp;gt; =&amp;gt;{ ... };  

  updateTodoDetails = async (  
    userId: string,  
    todoId: string,  
    todoDetails: Partial&amp;lt;ITodoModel\&amp;gt;  
  ): Promise&amp;lt;ITodoModel\&amp;gt; =&amp;gt; { ... };  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see from the above code example our todoTable is injected TodoRepository similarly any class satisfying this &lt;em&gt;TodoAppDataSource&lt;/em&gt; can be in injected into TodoRepository&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 5 (Database)
&lt;/h2&gt;

&lt;p&gt;At number 5 we have kept our data layer, it encapsulates all our DB queries and expose it with the single interface, there is one base class for each type of DB, refer example shown below for mongoDB and postgresql.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common interface&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface TodoAppDataSource&amp;lt;T\&amp;gt; {  
  create(data: T): Promise&amp;lt;T\&amp;gt;;  
  findOne(filter: Partial&amp;lt;T\&amp;gt;, project?: Projection): Promise&amp;lt;T\&amp;gt;;  
  findMany(filter: Partial&amp;lt;T\&amp;gt;, project?: Projection): Promise&amp;lt;T\[\]&amp;gt;;  
  findOneAndUpdate(filter: Partial&amp;lt;T\&amp;gt;, updates: Partial&amp;lt;T\&amp;gt;): Promise&amp;lt;T\&amp;gt;;  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;MongoDB base class&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class MongoDataSource&amp;lt;T&amp;gt; implements TodoAppDataSource&amp;lt;T&amp;gt; {  
  private table: mongoose.Model&amp;lt;T&amp;gt;;  
  constructor(tableName: DB\_TABLES) {  
    this.table = ALL\_TABLES\[tableName\] as mongoose.Model&amp;lt;T&amp;gt;;  
  }  

  public async findOne&amp;lt;T&amp;gt;(  
    selectQuery: Partial&amp;lt;T&amp;gt;,  
    project: Projection = {}  
  ): Promise&amp;lt;T&amp;gt; {  
    return this.table.findOne(selectQuery as FilterQuery&amp;lt;T&amp;gt;, project);  
  }  

  public async create&amp;lt;T&amp;gt;(data: T): Promise&amp;lt;T&amp;gt; {  
    const newRecord = new this.table(data);  
   return newRecord.save() as Promise&amp;lt;T&amp;gt;;  
  }  

  public async findOneAndUpdate&amp;lt;T&amp;gt;(  
    selectQuery: Partial&amp;lt;T&amp;gt;,  
    updates: Partial&amp;lt;T&amp;gt;  
  ): Promise&amp;lt;T&amp;gt; {  
    return this.table.findOneAndUpdate(selectQuery as FilterQuery&amp;lt;T&amp;gt;, updates, {  
      new: true,  
    });  
  }  

  public findMany = async (  
    filter: Partial&amp;lt;T&amp;gt;,  
    project?: Projection  
  ): Promise&amp;lt;Array&amp;lt;T&amp;gt;&amp;gt; =&amp;gt; {  
    const result = await this.table.find(filter as FilterQuery&amp;lt;T&amp;gt;, project);  
    return result as unknown as Promise&amp;lt;Array&amp;lt;T&amp;gt;&amp;gt;;  
  };  
}  

export class UserTable extends MongoDataSource&amp;lt;IUserModel\&amp;gt; {  
  constructor() {  
    super(DB\_TABLES.USER);  
  }  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Simillar to above mongoDB queries we can create class for any type of database and can inject this layer (layer 5 — DB) to other layer (layer 4 — Repository) by just taking care that it implements single interface for all DB base classes.&lt;/p&gt;

&lt;p&gt;I know this can be overwhelming for first time readers but trust me once your code repository is setup it will be very easy for you to scale your code, I request you to please go through code &lt;a href="https://github.com/aniketchanana/clean-code-node.js"&gt;from here&lt;/a&gt; start from main.ts.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Research is formalised curiosity, it is poking and prying with a purpose. There is no hard and fast rule of setting up or efficiently structuring the code repository. Hence exploring, investigating and experimenting is the best way suggested.&lt;/p&gt;

&lt;p&gt;The concise way of writing the code and structuring is the sole reason of this article. Any suggestions or corrections on this article are welcome. Will be back with another interesting article. Happy coding till then !&lt;strong&gt;❤&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>cleancode</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a Modular White Label Frontend with React and TypeScript</title>
      <dc:creator>Aniket</dc:creator>
      <pubDate>Mon, 01 Jan 2024 08:19:07 +0000</pubDate>
      <link>https://forem.com/aniketchanana/building-a-modular-white-label-frontend-with-react-and-typescript-419m</link>
      <guid>https://forem.com/aniketchanana/building-a-modular-white-label-frontend-with-react-and-typescript-419m</guid>
      <description>&lt;p&gt;&lt;strong&gt;Hello everyone!&lt;/strong&gt; In this article, I’ll be discussing how you can design a white-label product for web-based applications using React and TypeScript. &lt;/p&gt;

&lt;p&gt;Before we start do you want to learn &lt;strong&gt;software development?&lt;/strong&gt; with &lt;strong&gt;personalised classes&lt;/strong&gt; and &lt;strong&gt;mentorship&lt;/strong&gt; from a seasoned professional. With 4 years of hands-on experience contributing to top products used by industry giants like &lt;strong&gt;Amazon, Flipkart, Urban clap, meesho, Dominos, Swiggy etc.&lt;/strong&gt; I specialize in &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;Node.js&lt;/strong&gt;, &lt;strong&gt;TypeScript&lt;/strong&gt;, and &lt;strong&gt;System design&lt;/strong&gt;. Let’s elevate your career together! Reach out at &lt;strong&gt;&lt;a href="mailto:aniket.chanana@gmail.com"&gt;aniket.chanana@gmail.com&lt;/a&gt;&lt;/strong&gt; or connect on &lt;a href="https://www.linkedin.com/in/aniket-c-470471147/"&gt;&lt;strong&gt;LinkedIn&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A white-label solution refers to a product or service created by one entity and made available for use by others to conduct business. For instance, if you desire an image editing capability on your website without developing a new image editor, you can acquire a white-label solution. By customizing it to match your theme, you can seamlessly integrate and leverage it to enhance your business offerings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Before we delve deeper, let me highlight some of the key offerings of a white-label solution.
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; Easily integratable into any web application, enhancing its capabilities effortlessly.&lt;/li&gt;
&lt;li&gt; Offers customizable theming options to seamlessly align with the aesthetics of the host website.&lt;/li&gt;
&lt;li&gt; Facilitates smooth data flow between the host and child applications, ensuring seamless communication.&lt;/li&gt;
&lt;li&gt; Designed for ease of use, requiring minimal or no configuration for any third-party developer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Considering the points mentioned earlier, let me explain the process in a simple way. We will use a basic example — of a &lt;strong&gt;form submission application&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s take a look at the diagram below to get a basic understanding of the flow and application structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H3ECd2gr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2ARLvfpS459JTa4XtWp7SFVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H3ECd2gr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2ARLvfpS459JTa4XtWp7SFVQ.png" alt="" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also there are various methods to integrate your forms-app UI with the host app UI, like&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; via javascript &lt;em&gt;modules (npm module or&lt;/em&gt; &lt;em&gt;&lt;/em&gt; tags).&lt;/li&gt;
&lt;li&gt; via iFrame Integration by providing child app src &lt;em&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this article we will follow the &lt;strong&gt;2nd approach&lt;/strong&gt; because iframes provide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Isolation and Security.&lt;/li&gt;
&lt;li&gt; Ease of Implementation&lt;/li&gt;
&lt;li&gt; Cross-Domain Compatibility&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now Let’s jump into the code &amp;amp; build our &lt;strong&gt;white-label forms app&lt;/strong&gt; — &lt;em&gt;basically, it can plugged it into any app using an iframe and can be customised easily&lt;/em&gt;. you can check out the full code here: &lt;a href="https://github.com/aniketchanana/white-label-solution-design"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Here are the must-have things:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Keeping messages Structured&lt;/strong&gt;: Every message to and from the iframe follows the same structure. So that user cannot mess around — strict validation for all messages. ref: &lt;a href="https://github.com/aniketchanana/white-label-solution-design/blob/main/white-label-forms-app/src/utils/form.communication.utils.ts"&gt;&lt;strong&gt;Message validation function&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Data Check&lt;/strong&gt;: Our forms app checks any data that comes into the iframe before getting down to business logic. ref: &lt;a href="https://github.com/aniketchanana/white-label-solution-design/blob/main/white-label-forms-app/src/utils/useMessageHandler.tsx"&gt;&lt;strong&gt;Message handler hook&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Easy Peasy Form Fields&lt;/strong&gt;: Host apps can tweak form fields with a simple post iframe message. ref: &lt;a href="https://github.com/aniketchanana/white-label-solution-design/blob/main/host-app/src/App.tsx"&gt;&lt;strong&gt;Host app postMessage with field config&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Style It Your Way&lt;/strong&gt;: Our forms app supports some basic theming. So, if you’re integrating our iframe, you can make it look alike to match your app’s theme.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Out of Our Article’s Scope:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Fancy Theming&lt;/strong&gt;: We will touching on the basics of adding theming.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Complex Logic&lt;/strong&gt;: We will be skipping the complex logic. This article is all about the system design of a white-label frontend solution.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Forms app dashboard&lt;/strong&gt;: We won’t be developing any backend support for our forms application in this article; the focus here is purely on the frontend solution.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This article you what’s necessary and how to turn your app into a white-label app. You can grab these ideas and apply in your application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Froms app UI
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CVJW00Ls--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AGI_ATZ80MpsY8zcph2-EYA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CVJW00Ls--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AGI_ATZ80MpsY8zcph2-EYA.png" alt="" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Forms app UI and functionalities&lt;/p&gt;

&lt;p&gt;After building out config driven (ref: &lt;a href="https://github.com/aniketchanana/white-label-solution-design/blob/main/white-label-forms-app/src/fieldRenderer/index.tsx"&gt;FieldRenderer&lt;/a&gt;) UI lets setup our incoming messages handler.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting up communication for Forms app &amp;amp; Host app
&lt;/h4&gt;

&lt;p&gt;We will be having a communication between both our applications, e.g we will have a &lt;strong&gt;postMessage&lt;/strong&gt; function for sending messages to other froms-app and &lt;strong&gt;useMessageHandler&lt;/strong&gt; hook handle incoming messages. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As of now both the apps are under us so we can setup communication as per our wish, later when our &lt;strong&gt;Forms app&lt;/strong&gt; is consumed by any 3rd party &lt;strong&gt;Host app&lt;/strong&gt; in that case they can setup &lt;strong&gt;postMessage&lt;/strong&gt; functionality and &lt;strong&gt;message handler&lt;/strong&gt; functionality as per their wish.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iSbElZEm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AHLcpimF9BL4m9eXoVmUIUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iSbElZEm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AHLcpimF9BL4m9eXoVmUIUw.png" alt="" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This hook will handle all the incoming message + validation to our forms app (iframe)&lt;/p&gt;

&lt;p&gt;This hook will be responsible for all the validation of incoming message and our &lt;strong&gt;handleIncomingMessage&lt;/strong&gt; will be invoked as callback post validation from &lt;strong&gt;validateMessage&lt;/strong&gt;, and our &lt;strong&gt;handleIncomingMessage&lt;/strong&gt; function is responsible for routing correct message type to its &lt;strong&gt;business logic implementation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;strong&gt;business logic&lt;/strong&gt; will take payload from the message and make our app react accordingly e.g if message contains instructions to &lt;strong&gt;CHANGE_THEME&lt;/strong&gt; our app will invoke appropriate function for this and will change our app theme based on the message received.&lt;/p&gt;

&lt;p&gt;Similarly we will be having a &lt;strong&gt;postMessage&lt;/strong&gt; functionality for sending message to other app in.&lt;/p&gt;

&lt;p&gt;Now that our communication is setup between both the apps we can start sending message from &lt;strong&gt;host-app&lt;/strong&gt; to &lt;strong&gt;forms-app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9IQhxDLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AnW2-cF-CJsZvcvmA_kuKTQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9IQhxDLn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AnW2-cF-CJsZvcvmA_kuKTQ.png" alt="" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Function in host-app for sending message to froms-app&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TJtEiMo---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2ANk5GqfOTqTS0PydxtIODew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TJtEiMo---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2ANk5GqfOTqTS0PydxtIODew.png" alt="" width="642" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;message recieved in froms-app from host-app&lt;/p&gt;

&lt;p&gt;Now that we our INIT_FORM event is getting data from host-app which includes our theme details, fields config and other configurable parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We will use this data to drive our forms app UI using our message handler function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4WE6aAId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2A4AgQjUt5WC8IzC2pvn5cdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4WE6aAId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2A4AgQjUt5WC8IzC2pvn5cdw.png" alt="" width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Implementation for handling incoming messages to forms app&lt;/p&gt;

&lt;p&gt;You can refer &lt;a href="https://github.com/aniketchanana/white-label-solution-design/blob/main/white-label-forms-app/src/App.tsx"&gt;this file&lt;/a&gt; and understand how we are deriving our UI from the config sent via &lt;strong&gt;postMessage&lt;/strong&gt; from our host app.&lt;/p&gt;

&lt;p&gt;Now that our &lt;strong&gt;forms-app&lt;/strong&gt; is ready to handle our incoming data from host-app from here we can do what ever we want (i have console logged fieldValues), what you can do is&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Send this data back to &lt;strong&gt;host-app&lt;/strong&gt; from post message communication of iframe.&lt;/li&gt;
&lt;li&gt; Or Make an API call to froms app server and store data in the dashboard&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It totally depends on the Client usecase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ssH_RfVQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AX60wJR0EdniZ06d6kWqNgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ssH_RfVQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1600/1%2AX60wJR0EdniZ06d6kWqNgQ.png" alt="" width="800" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;onSubmit method gets invoked on form submission&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This is one way to create a user interface based on configuration settings. After working in software engineering for four years, I’ve found it to be a widely used approach in real-world applications because it offers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Easy Maintenance&lt;/strong&gt;: It’s simpler to manage and update.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Serve Multiple Clients&lt;/strong&gt;: You can use a single application to serve multiple clients (like in a SAAS scenario). Everything is controlled through configuration settings.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Effortless Updates&lt;/strong&gt;: You can deliver updates without requiring users to run npm install or upgrade modules.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope you find this article on &lt;strong&gt;configuration-driven UI&lt;/strong&gt; and how to &lt;strong&gt;white label any frontend application&lt;/strong&gt;. Any suggestions or corrections for this article are welcome. Stay tuned for more articles. Happy coding till then !&lt;strong&gt;❤&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
