DEV Community

Cover image for I Submitted Two Pull Requests to the Answer Platform
Ourai L.
Ourai L.

Posted on

I Submitted Two Pull Requests to the Answer Platform

It seems that the OpenBuild community ecosystem project has been on hold for quite some time. The initiator wants to quickly advance it, but there hasn't been much progress so far, and it's hard to find other suitable people for the jobโ€”so I had to take it over.

The project aims to develop a plugin for the open-source Q&A platform Answer that supports login via Web3 wallets. From the perspective of the functionality to be implemented, this should be a relatively small project, with an estimated total of 1.5 to 3 person-days for both front-end and back-end development and integration.

However, reality has given me a hard time...

Requirement Analysis

Initially, based on the official plugin development documentation, what we need to build is a connector-backend plugin.

With this in mind, I reviewed the code of several existing connectors and found that each plugin can only specify one type, and back-end plugins do not directly support UIsโ€”they all redirect to external authorization URLs.

However, there is no ready-made external authorization URL for Web3 wallet login. To meet the requirement, we might need to develop an additional router-standard UI plugin to create a page that:

  1. Displays a "Connect Wallet" button;
  2. After the wallet is connected, prompts the user to sign:
    1. Retrieve a nonce from the back-end, with the front end providing the wallet address;
    2. The front end invokes the wallet to get the user's signature;
  3. Call the back-end authorization interface after the signature is obtained, with the front end passing the user's signature information and wallet address;
  4. Return to the main interface upon successful request.

The parts in bold above require data interaction with the back-end, meaning we need two back-end APIs.

The process seems simple, right? And it really is!

Development Process

The back-end part was largely completed months ago, with only the front-end interface and integration remaining.

Since the project is not developed with a front-end and back-end separation, to run it fully, according to the official documentation, I would need to install Docker, a database, and other tools.

However, I had not installed these on my local machine before, and I have no plans to use them for other projects in the near future. I couldn't justify installing software that I would hardly use, just to save some disk space on my computer.

Therefore, I decided to first develop the front-end interface layout, styles, and functionality in a pure front-end manner, even though the back-end API requests would fail. Including the time spent reading the documentation and familiarizing myself with the basic plugin mechanism, it took me about 1 person-day to complete.

I scheduled a full-day integration session with the back-end developer over the weekend, hoping to finalize and deliver the project, but we encountered many setbacks...

Since I didn't have the back-end environment installed and configured on my local machine, I couldn't follow the normal plugin loading and running process. Some issues that I didn't encounter during the development phase emerged when the back-end developer tried to run the entire process with my code.

Initially, whenever we encountered a front-end issue, we would start a video call to see how he was operating, and I would guide him on how to solve it. After a few times, I suddenly realizedโ€”this is what people call "pair programming"! ๐Ÿ˜‚๐Ÿ˜‚๐Ÿ˜‚

Later, I thought to myself: "This is not sustainable; it's too inefficient!"

Eventually, I decided to let go of my hesitation and let him guide me on how to set up the back-end environment so that I could test and adjust the front-end code myself.

After being guided, I found out that I actually only needed to install Go, and I could use the SQLite database that comes with macOSโ€”no need for Docker at all. I really should have let him be my "navigator" from the beginning!

Although things didn't go smoothly afterwards, we no longer needed to hold video calls. We could just send a screenshot and a brief description via WeChat whenever we encountered a problem, which greatly improved our efficiency!

While testing the plugin I developed, I also discovered a bug in the plugin loading mechanism and fixed it with a PR, earning an extra achievement! ๐Ÿ˜๐Ÿ˜๐Ÿ˜

After a day or two of final touches, we delivered the plugin. Under the guidance and suggestions of the official reviewer, we merged the original two plugins into one hereโ€”it appears to be a "router-standard UI plugin", but it is also a "connector-backend plugin" in reality.

In just three to five days, we managed to resolve the "constipation" issue, and it's time to celebrate! ๐ŸŽ‰๐ŸŽ‰๐ŸŽ‰

Pitfalls and Experiences

This project was developed based on the main project version 1.4.0. The incomplete official documentation, the plugin system, and my own somewhat awkward mindset led me to encounter some pitfalls. Below, I share some key points for local debugging for front-end developers to avoid unnecessary detours!

Firstly, for those who, like me, are concerned about thisโ€”you only need to install Go additionally, and you can use the SQLite database that comes with macOS!

Taking the plugin we developed as an example, let's assume the plugin is named connector-wallet.

Back-end Environment

Ensure that the plugin package is imported in the main project's cmd/answer/main.go, even if it does not exist yet:

import (
  answercmd "github.com/apache/incubator-answer/cmd"

  _ "github.com/apache/incubator-answer-plugins/connector-wallet"
)
Enter fullscreen mode Exit fullscreen mode

Whether it is a pure front-end plugin or a plugin that appears to be a front-end plugin, when debugging, the code generated by the template should be placed in the ui/src/plugins folder, and a go.work file should be created in the root folder:

go 1.22.0

toolchain go1.23.2

use (
    .
    ./ui/src/plugins/connector-wallet
)
Enter fullscreen mode Exit fullscreen mode

Run make ui to build the front-end code, and then compile the back-end code with go build -o answer ./cmd/answer/main.go, which will generate the answer file. All subsequent operations will use this file.

Run ./answer init -C ./answer-data/ to initialize the system. You need to visit http://localhost in the browser to fill in the information, where the database should be selected as SQLite, and the file storage path should replace /data with the absolute path of the answer-data folder.

Run ./answer run -C ./answer-data/ to start the back-end service. Visit http://localhost again to log in with the initial account and enable the plugin you want to debug in the back-end!

Finally, change the REACT_APP_API_URL in ui/.env.development to http://localhost:80/, and you can start the front-end development server to access the back-end API.

Front-end Environment

After installing the dependencies, you need to delete several folders in the plugin folder to avoid issues:

  • Delete the dist folder and the main, module, types, and exports fields in the package.json, otherwise the page will render the compiled files, and changes to the source files will not trigger a refresh;
  • Delete the node_modules folder, otherwise the i18n configuration read by the plugin may not be from the main project, possibly due to react-i18next not using a singleton pattern, resulting in two separate configurations.

Publishing the Plugin

If the front-end plugin adds additional dependencies, you need to modify the vite.config.ts configuration in the plugin package:

import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js';

export default defineConfig({
  plugins: [
    ...,
    cssInjectedByJsPlugin(),    // Required when importing style files, otherwise styles will be disordered
    ...,
  ],
  build: {
    ...,
    rollupOptions: {
      external: [
        ...,    // Declare your additional dependencies here
      ],
      output: {
        globals: {
          ...,    // Declare your additional dependencies here
        },
      },
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Conclusion

Thank you to OpenBuild for providing this opportunity. Although I was reluctant to take it on at first because I thought there were more important and urgent matters to attend to, time can always be squeezed out if you really want to!

Thank you to the back-end developer for the great cooperation, which helped us resolve this "constipation" issue that had been lingering for months!

Thank you to the Answer official reviewers for accompanying me through the PR process and helping me practice my English, which has set a good foundation for my future international development!

Although I have contributed PRs to several other open-source projects before, they were mostly minor fixes and didn't involve much communication before being merged. This contribution to Answer truly gave me the feeling of being part of an open-source community!

Salute to all OPEN SOURCERORs!!!

Top comments (0)