There seems to be an OpenBuild community ecological project that has been stalled for a while. The initiator wants to continue pushing it forward quickly, but there hasn't been much progress, and suitable people are hard to find—so I have no choice but to take it over.
The goal of this project is to develop a plugin for the open-source Q&A platform Answer that supports logging in with a Web3 wallet. From the functionality perspective, this should be a small project, and the development plus front-end and back-end integration is estimated to take about 1.5 to 3 person-days.
However, reality hit me hard...
Requirement Analysis#
From the official plugin development documentation, it seems that what needs to be done is a "connector-backend plugin."
With this premise, I roughly understood the code of several existing connectors and found that each plugin can only specify one type, and backend plugins cannot directly support UI; they all redirect to external authorization URLs.
However, there is no ready-made external authorization URL for Web3 wallet login, so to meet the requirements, it may be necessary to write a supporting "router-standard UI plugin" and develop a page:
- Display a connect wallet button;
- After connecting the wallet, the user signs;
- Get nonce from the backend, and the front end passes in the wallet address;
- The front end invokes the wallet for the user to sign;
- After signing, call the backend authorization interface, passing in the user signature information, wallet address, etc.;
- After a successful request, return to the main interface.
The bolded parts above require data interaction with the backend, meaning there need to be two backend interfaces.
The process looks simple, right? And it really is quite simple!
Development Process#
The backend part was mostly completed a few months ago, and it was basically just the front-end interface and integration that were missing.
Since this project does not have a front-end and back-end separation, if I want to run it completely, according to the information in the official documentation, I need to install Docker, a database, etc.
However, I hadn't installed these locally before, and I currently have no plans for other projects that require them, so it’s not feasible to install software that I would hardly use just to save precious computer storage space.
So, I first adopted a purely front-end approach to develop the layout, style, and functionality of the interface, even if the backend interface requests failed; including the time spent reading documentation and familiarizing myself with the basic mechanisms of the plugin, I probably spent about 1 person-day to complete it.
I scheduled a day on the weekend with the person responsible for the backend to focus on integration, hoping to get the delivery done, but I faced continuous setbacks...
Because I hadn't installed and set up the backend environment locally, I couldn't follow the normal plugin loading and running process, and some issues that I hadn't encountered during the development phase arose; when I asked the backend colleague to download my code and run the whole process, all sorts of "strange" problems popped up...
At first, whenever there was a front-end issue, I would initiate a video meeting to see how he was operating, and I would guide him to solve it—after a few times, I suddenly realized, isn’t this the legendary "pair programming"? 😂😂😂
Later I thought, "This won't work, it's just too inefficient!"
In the end, I tried to put aside my reservations and let him guide me on how to get the backend running, so I could test and adjust the front-end code myself.
After being guided, I found that I really only needed to install Go, and I could directly use the SQLite that comes with macOS for the database, without needing to mess with Docker— I really should have let him be my "navigator" from the start!
Although things didn't go smoothly afterward, we no longer needed to hold video meetings; if there was an issue, we just needed to send a screenshot and a brief description on WeChat, greatly improving efficiency!
While testing the plugin I developed, I also discovered a bug in the plugin loading mechanism, so I quickly fixed it and submitted a PR, achieving an extra +1! 😁😁😁
After a day or two of wrapping things up, the plugin we developed was delivered, and under the guidance and suggestions of the official reviewers, we merged the original two plugins into one—on the surface, it is a "router-standard UI plugin," but in reality, it is also a "connector-backend plugin."
Thus, we resolved the "constipation" issue in these three to five days, let’s celebrate! 🎉🎉🎉
Pitfall Experiences#
This development was based on the main project version 1.4.0, and the imperfections in the official documentation and plugin system, along with my somewhat awkward mindset, led me to encounter some pitfalls. Below, I will share some key points for local debugging aimed at front-end developers to help avoid detours!
First, for those like me who care—you only need to install Go, and you can use the SQLite that comes with macOS for the database!
Taking our developed plugin as an example, assuming the plugin name is connector-wallet
—
Backend Environment#
Ensure that the plugin package is imported in the main project’s cmd/answer/main.go
, even if it currently does not exist:
import (
answercmd "github.com/apache/incubator-answer/cmd"
_ "github.com/apache/incubator-answer-plugins/connector-wallet"
)
Whether it is a pure front-end plugin or a "superficially front-end plugin," during 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
)
Execute make ui
to build the front-end code, then use go build -o answer ./cmd/answer/main.go
to compile the backend code, which will generate the answer
file, and all subsequent operations will use it.
Execute ./answer init -C ./answer-data/
to initialize the system, and you need to visit http://localhost
in the browser to fill in the information, where you should select SQLite for the database and replace /data
with the absolute path of the answer-data
folder.
Execute ./answer run -C ./answer-data/
to start the backend service, and visit http://localhost
again to log in to the initial account and enable the plugin you want to debug in the backend!
Finally, change REACT_APP_API_URL
in ui/.env.development
to http://localhost:80/
to start the front-end development server to access the backend interface.
Frontend Environment#
After installing the dependencies, you need to delete several folders under the plugin folder to avoid issues:
- Delete the
dist
folder and themain
,module
,types
, andexports
fields inpackage.json
, otherwise the page will render the compiled files, and changes to the source files will not trigger a refresh; - Delete
node_modules
, otherwise the i18n configuration read in the plugin will not be from the main project, which may be due toreact-i18next
not using a singleton pattern at the underlying level, resulting in two configurations.
Publishing the Plugin#
If additional dependencies are added to the front-end plugin, you need to modify the configuration in vite.config.ts
of the plugin package:
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js';
export default defineConfig({
plugins: [
...,
cssInjectedByJsPlugin(), // Must be included when there are style files, otherwise styles will be messed up
...,
],
build: {
...,
rollupOptions: {
external: [
..., // Declare your additional dependencies
],
output: {
globals: {
..., // Declare your additional dependencies
},
},
},
},
});
Conclusion#
Thanks to OpenBuild for providing this opportunity. Although I was initially reluctant to take it on because I thought I had more important and prioritized tasks to do... but if you squeeze time, there will still be some!
Thanks to the backend colleagues for their active cooperation, allowing us to solve this "constipation" issue that had been dragging on for months!
Thanks to the official reviewers of Answer for helping me practice English in the PR, which has set a good precedent for my future international development!
Although I had submitted PRs to several other open-source projects before, they were mostly minor fixes, and there was hardly any communication before they were merged directly; contributing to Answer gave me a real sense of doing open source!
Salute to all OPEN SOURCERORs!!!
Other reading addresses for this article: Personal Website|WeChat Official Account