{"id":13470407,"url":"https://github.com/grz0zrg/fbg","last_synced_at":"2025-05-15T20:04:40.127Z","repository":{"id":35574386,"uuid":"137663804","full_name":"grz0zrg/fbg","owner":"grz0zrg","description":"Lightweight C 2D graphics API agnostic library with parallelism support","archived":false,"fork":false,"pushed_at":"2024-12-08T16:16:30.000Z","size":4131,"stargazers_count":515,"open_issues_count":7,"forks_count":41,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-04-08T02:41:15.434Z","etag":null,"topics":["2d-graphics","embedded","fbdev","framebuffer","gba","graphics","graphics-library","graphics-rendering","library","lightweight","multi-core","multithreaded","multithreading","opengl"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grz0zrg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-17T15:04:22.000Z","updated_at":"2025-04-02T14:44:41.000Z","dependencies_parsed_at":"2024-01-14T04:58:32.283Z","dependency_job_id":"d6e8549b-0a97-435c-9069-c6de10bf6019","html_url":"https://github.com/grz0zrg/fbg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grz0zrg%2Ffbg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grz0zrg%2Ffbg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grz0zrg%2Ffbg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grz0zrg%2Ffbg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grz0zrg","download_url":"https://codeload.github.com/grz0zrg/fbg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414499,"owners_count":22067272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2d-graphics","embedded","fbdev","framebuffer","gba","graphics","graphics-library","graphics-rendering","library","lightweight","multi-core","multithreaded","multithreading","opengl"],"created_at":"2024-07-31T16:00:29.847Z","updated_at":"2025-05-15T20:04:34.232Z","avatar_url":"https://github.com/grz0zrg.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"FBGraphics : Lightweight C 2D graphics API agnostic library with parallelism support\n=====\n\nFBGraphics (FBG) is a simple C 24, 32 bpp (internal format) graphics library with parallelism and custom rendering backend support (graphics API agnostic).\n\nThe library is only two .c files on most use cases, the renderer agnostic library `fbgraphics.c` and one of the rendering backend found in `custom_backend` directory.\n\nThe library come with five backend (see `custom_backend` folder) : \n * a Linux framebuffer rendering backend (with 16 bpp support through 24/32 bpp conversion)\n * OpenGL backend which use the [GLFW](http://www.glfw.org/) library\n * OpenGL ES 2.0 backend for fbdev or Raspberry PI\n * fast dispmanx backend (Video Core IV; Raspberry PI)\n * GBA backend (slow due to 24/32 bpp -\u003e 16 bpp support, mostly done as a proof of concept for portability on low memory hardware)\n\nFeatures :\n\n * Easy to write / use custom rendering backend support flexible enough to target low memory hardware!\n * Cross-platform with the GLFW backend (some examples may need to be adapted to the target OS)\n * Linux framebuffer (fbdev) rendering backend support\n    * Double buffering (with optional page flipping mechanism)\n    * 16, 24 (BGR/RGB), 32 bpp support\n * GBA rendering backend\n * OpenGL rendering backend through GLFW\n * OpenGL ES 2.0 rendering backend for Raspberry PI or through fbdev (tested on Nano PI Fire 3 board)\n * dispmanx rendering backend (Video Core IV; Raspberry PI)\n * Optional : Full parallelism, execute graphics code on multiple CPU cores **with a single function**\n * Image loading (provided by [LodePNG](https://lodev.org/lodepng/), [NanoJPEG](http://keyj.emphy.de/nanojpeg/), and [stb_image](https://github.com/nothings/stb/blob/master/stb_image.h))\n * Bitmap fonts for drawing texts\n * Bare-metal graphics primitive (pixels, rectangles, lines, polygon)\n * Easy to do fading, clipping and screen-clearing related effects (motion blur etc.)\n * Drawing calls can be used to render into a specified target buffer such as fbg_image etc.\n * Framerate tracking \u0026 display for all cores\n * Lightweight enough to be hackable; adapt to all kinds of needs (and still support parallelism easily)\n\nThe library is generic, most functions (including parallel ones) only manipulate buffers and you can build a custom rendering backend pretty easily with few functions call, see the `custom_backend` folder.\n\nDoxygen documentation : https://grz0zrg.github.io/fbg/\n\nTable of Contents\n=================\n\n* FBGraphics\n   * [About](#about)\n      * [Quickstart](#quickstart)\n      * [Parallelism](#parallelism)\n      * [Technical implementation](#technical-implementation)\n   * [Benchmark](#benchmark)\n   * [Documentation](#documentation)\n   * [Building](#building)\n   * [Rendering backend](#Rendering-backend)\n   * [GLFW backend](#GLFW-backend)\n   * [OpenGL ES 2.0 backend](#OpenGL-ES-2-backend)\n   * [Screenshots](#screenshots)\n   * [License](#license)\n\n## About\n\nFBGraphics was built to produce fullscreen pixels effects easily (think of Processing-like creative coding etc.) with non-accelerated framebuffer by leveraging multi-core processors, it is a bit like a software GPU but much less complex and featured, the initial target platform was a Raspberry PI 3B / NanoPI.\n\nFBGraphics was extended to support any numbers of custom rendering backend; all graphics calls manipulate internal buffers and a simple interface allow to draw the result the way you want to.\n\nFBGraphics can support low memory hardware such as GBA. It should be noted that all internal buffers are manipulated in 24/32 bpp so it has to convert to 16bpp on GBA.\n\nAn OpenGL rendering backend which use the [GLFW library](http://www.glfw.org/) was created to demonstrate the custom backend feature, it allow to draw the non-accelerated FB Graphics buffer into an OpenGL context through a texture and thus allow to interwine 3D or 2D graphics produced with standard OpenGL calls with CPU-only graphics produced by FBGraphics draw calls.\n\nAn OpenGL ES 2.0 backend is also available with similar features, it target platforms with support for OpenGL ES 2.0 through fbdev (tested on Nano PI Fire 3 SBC) or Raspberry PI dispmanx and similar platforms, it wouldn't be hard to extend this for more OpenGL ES 2.0 platforms...\n\nThere is also a dispmanx backend targeting Raspberry PI, it have better performances than the OpenGL ES 2 backend on this platform and is recommended if you don't need 3D stuff.\n\nFBGraphics was built so that it is possible to create any number of rendering context using different backend running at the same time while exploiting multi-core processors... the content of any rendering context can be transfered into other context through images when calling `fbg_drawInto`\n\nFBGraphics framebuffer settings support 16, 24 (BGR/RGB), 32 bpp, 16 bpp mode is handled by converting from 24 bpp to 16 bpp upon drawing, page flipping mechanism is disabled in 16 bpp mode, **24 bpp is the fastest mode**.\n\nFBGraphics is lightweight and does not intend to be a fully featured graphics library, it provide a limited set of graphics primitive and a small set of useful functions to start doing computer graphics anywhere right away with or without multi-core support.\n\nIf you want to use the parallelism features with advanced graphics primitives, take a look at great libraries such as [libgd](http://libgd.github.io/), [Adafruit GFX library](https://github.com/adafruit/Adafruit-GFX-Library) or even [ImageMagick](https://imagemagick.org) which should be easy to integrate.\n\nFBGraphics is fast but should be used with caution, display bounds checking is not implemented on most primitives, this allow raw performances at the cost of crashs if not careful.\n\nMulti-core support is optional and is only enabled when `FBG_PARALLEL` C definition is present.\n\nFBGraphics framebuffer backend support a mechanism known as page flipping, it allow fast double buffering by doubling the framebuffer virtual area, it is disabled by default because it is actually slower on some devices. You can enable it with a `fbg_fbdevSetup` call.\n\nVSync is automatically enabled if supported.\n\n**Note** : FBGraphics framebuffer backend does not let you setup the framebuffer, it expect the framebuffer to be configured prior launch with a command such as :\n\n```\nfbset -fb /dev/fb0 -g 512 240 512 240 24 -vsync high\nsetterm -cursor off \u003e /dev/tty0\n```\n\n`fbset` should be available in your package manager.\n\n### Framebuffer Quickstart\n\nThe simplest example (no parallelism, without texts and images) :\n\n```c\n#include \u003csys/stat.h\u003e\n#include \u003csignal.h\u003e\n\n#include \"fbg_fbdev.h\"\n#include \"fbgraphics.h\"\n\nint keep_running = 1;\n\nvoid int_handler(int dummy) {\n    keep_running = 0;\n}\n\nint main(int argc, char* argv[]) {\n    signal(SIGINT, int_handler);\n\n    struct _fbg *fbg = fbg_fbdevSetup(\"/dev/fb0\", 0); // you can also directly use fbg_fbdevInit(); for \"/dev/fb0\", last argument mean that will not use page flipping mechanism  for double buffering (it is actually slower on some devices!)\n\n    do {\n        fbg_clear(fbg, 0); // can also be replaced by fbg_fill(fbg, 0, 0, 0);\n\n        fbg_draw(fbg);\n\n        fbg_rect(fbg, fbg-\u003ewidth / 2 - 32, fbg-\u003eheight / 2 - 32, 16, 16, 0, 255, 0);\n\n        fbg_pixel(fbg, fbg-\u003ewidth / 2, fbg-\u003eheight / 2, 255, 0, 0);\n\n        fbg_flip(fbg);\n\n    } while (keep_running);\n\n    fbg_close(fbg);\n\n    return 0;\n}\n\n```\n\nA simple quickstart example with most features (but no parallelism, see below) :\n\n```c\n#include \u003csys/stat.h\u003e\n#include \u003csignal.h\u003e\n\n#include \"fbg_fbdev.h\"\n#include \"fbgraphics.h\"\n\nint keep_running = 1;\n\nvoid int_handler(int dummy) {\n    keep_running = 0;\n}\n\nint main(int argc, char* argv[]) {\n    signal(SIGINT, int_handler);\n\n    struct _fbg *fbg = fbg_fbdevInit();\n\n    struct _fbg_img *texture = fbg_loadImage(fbg, \"texture.png\");\n    struct _fbg_img *bb_font_img = fbg_loadImage(fbg, \"bbmode1_8x8.png\");\n\n    struct _fbg_font *bbfont = fbg_createFont(fbg, bb_font_img, 8, 8, 33);\n\n    do {\n        fbg_clear(fbg, 0);\n\n        fbg_draw(fbg);\n\n        // you can also use fbg_image(fbg, texture, 0, 0)\n        // but you must be sure that your image size fit on the display\n        fbg_imageClip(fbg, texture, 0, 0, 0, 0, fbg-\u003ewidth, fbg-\u003eheight);\n\n        fbg_write(fbg, \"Quickstart example\\nFPS:\", 4, 2);\n        fbg_write(fbg, fbg-\u003efps_char, 32 + 8, 2 + 8);\n\n        fbg_rect(fbg, fbg-\u003ewidth / 2 - 32, fbg-\u003eheight / 2 - 32, 16, 16, 0, 255, 0);\n\n        fbg_pixel(fbg, fbg-\u003ewidth / 2, fbg-\u003eheight / 2, 255, 0, 0);\n\n        fbg_flip(fbg);\n\n    } while (keep_running);\n\n    fbg_freeImage(texture);\n    fbg_freeImage(bb_font_img);\n    fbg_freeFont(bbfont);\n\n    fbg_close(fbg);\n\n    return 0;\n}\n```\n\n**Note** : Functions like `fbg_clear` or `fbg_fpixel` are fast functions, there is slower equivalent (but more parametrable) such as `fbg_background` or `fbg_pixel`, some functions variant also support transparency such as ``fbg_pixela` or `fbg_recta`.\n\n**Note** : You can generate monospace bitmap fonts to be used with `fbg_createFont` function by using my [monoBitmapFontCreator](https://github.com/grz0zrg/monoBitmapFontCreator) tool available [here](https://fbg-bitmap-font-creator.netlify.com/)\n\n### Parallelism\n\nExploiting multiple cores with FBGraphics is really easy, first you have to prepare 3 functions (of which two are optional if you don't have any allocations to do) of the following definition :\n\n```c\n// optional function\nvoid *fragmentStart(struct _fbg *fbg) {\n    // typically used to allocate your per-thread data\n    // see full_example.c for more informations\n\n    return NULL; // return your user data here\n}\n```\n\n```c\nvoid fragment(struct _fbg *fbg, struct _fragment_user_data *user_data) {\n    // this function will be executed by each threads\n    // you are free to call any FBG graphics primitive here\n    \n    fbg_clear(fbg, 0);\n    \n    // you are also free to fill each threads back buffer the way you want to\n    // fbg-\u003etask_id : thread identifier (starting at 1, 0 is reserved for the main thread)\n    // each threads will draw an horizontal line, the shade of the blue color will change based on the thread it is drawn from\n    int x = 0, y = 0;\n    for (y = fbg-\u003etask_id; y \u003c fbg-\u003eheight; y += 4) {\n        for (x = 0; x \u003c fbg-\u003ewidth; x += 1) {\n            int i = (x + y * fbg-\u003ewidth) * 3;\n            fbg-\u003eback_buffer[i] = fbg-\u003etask_id * 85; // note : BGR format\n            fbg-\u003eback_buffer[i + 1] = 0;\n            fbg-\u003eback_buffer[i + 2] = 0;\n        }\n    }\n    \n    // simple graphics primitive (4 blue rectangle which will be handled by different threads in parallel)\n    fbg_rect(fbg, fbg-\u003etask_id * 32, 0, 32, 32, 0, 0, 255);\n}\n```\n\n```c\n// optional function\nvoid fragmentStop(struct _fbg *fbg, struct _fragment_user_data *data) {\n    // typically used to free your per-thread data\n    // see full_example.c for more informations\n}\n```\n\nThen you have to create a 'Fragment' which is a FBG multi-core task :\n\n```c\nfbg_createFragment(fbg, fragmentStart, fragment, fragmentStop, 3);\n```\n\nWhere :\n\n* `fbg` is the main library data structure returned by `fbg_customSetup` and any backend `fbg_backendnameSetup` calls (see available backends in `custom_backend` directory)\n* `fragmentStart`is a C function which will be executed when the thread start (can be NULL)\n* `fragment`is a C function which will be executed indefinitly for each threads and where all the draw code will happen\n* `fragmentStop` is a C function which will be executed when the thread end  (can be NULL)\n* `3`is the number of parallel tasks (this will launch 3 threads)\n\nAnd finally you just have to make a call to your fragment function in your drawing loop and call  `fbg_draw`!\n\n```c\nfragment(fbg, NULL);\nfbg_draw(fbg, NULL);\n```\n\n`fbg_draw` will wait until all the data are received from all the threads then draw to screen\n\n**Note** : This example will use 4 threads (including your app one) for drawing things on the screen but calling the fragment function in your drawing loop is totally optional, you could for example make use of threads for intensive drawing tasks and just use the main thread to draw the GUI or the inverse etc. it is up to you!\n\nAnd that is all you have to do!\n\nSee `simple_parallel_example.c` and `full_example.c` for more informations.\n\n**Note** : By default, the resulting buffer of each tasks are additively mixed into the main back buffer, you can override this behavior by specifying a mixing function as the last argument of `fbg_draw` such as :\n\n```c\n// function called for each tasks in the fbg_draw function\nvoid selectiveMixing(struct _fbg *fbg, unsigned char *buffer, int task_id) {\n    // fbg is the main fbg structure returned by fbg_customSetup calls and any backend setup calls\n    // buffer is the current task buffer\n    // task_id is the current task id\n    int j = 0;\n    for (j = 0; j \u003c fbg-\u003esize; j += 1) {\n        fbg-\u003eback_buffer[j] = (fbg-\u003eback_buffer[j] \u003e buffer[j]) ? fbg-\u003eback_buffer[j] : buffer[j];\n    }\n}\n```\n\nThen you just have to specify it to the `fbg_draw` function :\n\n```c\nfbg_draw(fbg, additiveMixing);\n```\n\nBy using the mixing function, you can have different layers handled by different cores with different compositing rule, see `compositing.c` for an example of alpha blending compositing 2 layers running on their own cores.\n\n**Note** : You can only create one Fragment per fbg instance, another call to `fbg_createFragment` will stop all tasks for the passed fbg context and will create a new set of tasks.\n\n**Note** : On low performances platforms you may encounter performance issues at high resolution and with a high number of fragments, this is because all the threads buffer need to be mixed back onto the main thread before being displayed and at high resolution / threads count that is alot of pixels to process! You can see an alternative implementation using pure pthread in the `custom_backend` folder and `dispmanx_pure_parallel.c` but it doesn't have compositing. If your platform support some sort of SIMD instructions you could also do all the compositing using SIMD which should result in a 5x or more speed increase!\n\n### Technical implementation\n\nFBGraphics threads come with their own fbg context data which is essentialy a copy of the actual fbg context, they make use of C atomic types.\n\nInitially parallelism was implemented using [liblfds](http://liblfds.org/) library for its Ringbuffer and Freelist data structure.\n\nNow parallelism has two implementation, liblfds and a custom synchronization mechanism which has the advantage to not require additional libraries and thus execute on more platforms.\n\nYou can still use the liblfds implementation using the `FBG_LFDS` define, it may be faster.\n\n#### With liblfds\n\nEach threads begin by fetching a pre-allocated buffer from a freelist, then the fragment function is called to fill that buffer, the thread then place the buffer into a ringbuffer data structure which will be fetched upon calling `fbg_draw`, the buffers are then mixed into the main back buffer and put back into the freelist.\n\n#### Without liblfds\n\nEach threads fragment function is called to fill the local buffer, each threads then wait till that buffer is consumed by the main thread upon calling `fbg_draw`, the buffers are then mixed into the main back buffer and `fbg_draw` wake up all threads.\n\n## Benchmark (framebuffer)\n\nA simple unoptimized per pixels screen clearing with 4 cores on a Raspberry PI 3B :  30 FPS @ 1280x768 and 370 FPS @ 320x240\n\nNote : Using the dispmanx backend a screen clearing + rectangle moving on a Raspberry PI 3B : 60 FPS @ 1920x1080\n\n### Full example\n\nFullscreen per pixels perlin noise with texture mapping and scrolling (unoptimized)\n\n**Device** : Raspberry PI 3B ( Quad Core 1.2GHz )\n\n**Settings** : 320x240\n\n| Cores used to draw graphics | FPS     |\n| :-------------------------- | :------ |\n| 1                           | 42 FPS  |\n| 2                           | 81 FPS  |\n| 3                           | 120 FPS |\n\nSee screenshots below.\n\n### Tunnel example\n\nFullscreen texture-mapped and animated tunnel made of 40800 2px rectangles with motion blur (unoptimized)\n\n**Device** : Raspberry PI 3B ( Quad Core 1.2GHz )\n\n**Settings** : 320x240\n\n| Cores used to draw graphics | FPS     |\n| :-------------------------- | :------ |\n| 1                           | 36 FPS  |\n| 2                           | 69 FPS  |\n| 3                           | 99 FPS |\n| 4                           | 66 FPS |\n\nNote : The framerate drop with 4 cores is due to the main thread being too busy which make all the other threads follow due to the synchronization.\n\nSee screenshots below.\n\n## Documentation\n\nAll usable functions and structures are documented in the `fbgraphics.h` file with [Doxygen](http://www.stack.nl/~dimitri/doxygen/)\n\nThe HTML documentation can be found in the `docs` directory, it is also hosted on GitHub [here](https://grz0zrg.github.io/fbg/)\n\nExamples demonstrating all features are available in the `examples` directory.\n\nSome effects come from [my Open Processing sketches](https://www.openprocessing.org/user/130883#sketches)\n\n## Building\n\nC11 standard should be supported by the C compiler.\n\nAll examples found in `examples` directory make use of the framebuffer device `/dev/fb0` and can be built by typing `make` into the examples directory then run them by typing `./run_quickstart` for example (this handle the framebuffer setup prior launch), you will need to compile liblfds for the parallelism features. (see below)\n\nAll examples were tested on a Raspberry PI 3B with framebuffer settings : 320x240 24 bpp\n\nFor the default build (no parallelism), FBGraphics come with a header file `fbgraphics.h` and a C file `fbgraphics.c` to be included / compiled / linked with your program plus one of the rendering backend found in `custom_backend` directory, you will also need to compile the `lodepng.c` library and `nanojpeg.c` library, see the examples directory for examples of Makefile.\n\nFor parallelism support, `FBG_PARALLEL` need to be defined.\n\nIf you need to use the slightly different parallelism implementation (see technical implementation section) you will need the [liblfds](http://liblfds.org/) library :\n\n * Get latest liblfds 7.1.1 package on the official website\n * uncompress, go into the directory `liblfds711`\n * go into the directory `build/gcc_gnumake`\n * type `make` in a terminal\n * `liblfds711.a` can now be found in the `bin` directory, you need to link against it when compiling (see examples)\n\nTo compile liblfds parallel examples, just copy `liblfds711.a` / `liblfds711.h` file and `liblfds711` directory into the `examples` directory then type `make lfds711`.\n\n**Note** : FBGraphics with liblfds work on ARM64 platforms but you will need liblfds720 which is not yet released.\n\n### Executable size optimization\n\nThis library may be used for size optimized executable for things like [demos](https://en.wikipedia.org/wiki/Demoscene)\n\nImage support can be disabled with the following defines:\n- `WITHOUT_JPEG`\n- `WITHOUT_PNG`\n- `WITHOUT_STB_IMAGE`\n\nSee `tiny` makefile rule inside the `custom_backend` or `examples` folder for some compiler optimizations related to executable size.\n\nUnder Linux [sstrip](https://github.com/BR903/ELFkickers/tree/master/sstrip) and [UPX](https://upx.github.io/) can be used to bring the size down even futher.\n\n## Rendering backend\n\nSee `README` into `custom_backend` folder\n\n## GLFW backend\n\nSee `README` into `custom_backend` folder\n\nThe GLFW backend was made to demonstrate how to write a backend but it is complete enough to be used by default.\n\nThe GLFW backend has a cool lightweight Lua example which setup a Processing-like environment making use of the parallelism feature of the library, allowing the user to prototype multithreaded graphical stuff without C code compilation through the Lua language.\n\n## OpenGL ES 2 backend\n\nSee `README` into `custom_backend` folder\n\n## GBA backend\n\nSee `README` into `custom_backend` folder\n\n## Screenshots\n\n![Full example screenshot with three threads](/screenshot1.png?raw=true \"Full example screenshot with three threads\")\n\n![Tunnel with four threads](/screenshot2.png?raw=true \"Tunnel with four threads\")\n\n![Earth with four threads](/screenshot3.png?raw=true \"Earth with four threads\")\n\n![Flags of the world with four threads](/screenshot4.png?raw=true \"Flags of the world with four threads\")\n\n![Compositing with three threads](/screenshot5.png?raw=true \"Compositing with three threads\")\n\n## License\n\nBSD, see LICENSE file\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrz0zrg%2Ffbg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrz0zrg%2Ffbg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrz0zrg%2Ffbg/lists"}