{"id":14483104,"url":"https://github.com/dgarnitz/vectorflow","last_synced_at":"2025-12-14T12:04:57.810Z","repository":{"id":187493565,"uuid":"670696350","full_name":"dgarnitz/vectorflow","owner":"dgarnitz","description":"VectorFlow is a high volume vector embedding pipeline that ingests raw data, transforms it into vectors and writes it to a vector DB of your choice. ","archived":false,"fork":false,"pushed_at":"2024-05-16T20:31:48.000Z","size":394,"stargazers_count":694,"open_issues_count":15,"forks_count":51,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-07-05T13:49:04.812Z","etag":null,"topics":["ai","data-engineering","embeddings","machine-learning","nlp","vectors"],"latest_commit_sha":null,"homepage":"https://www.getvectorflow.com/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dgarnitz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-25T16:13:07.000Z","updated_at":"2025-06-05T17:22:13.000Z","dependencies_parsed_at":"2024-04-06T00:28:10.253Z","dependency_job_id":"ca2ce095-6a59-4e00-a068-e403d45c3fa0","html_url":"https://github.com/dgarnitz/vectorflow","commit_stats":null,"previous_names":["dgarnitz/vectorflow"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dgarnitz/vectorflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgarnitz%2Fvectorflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgarnitz%2Fvectorflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgarnitz%2Fvectorflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgarnitz%2Fvectorflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dgarnitz","download_url":"https://codeload.github.com/dgarnitz/vectorflow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dgarnitz%2Fvectorflow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272800743,"owners_count":24995138,"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","status":"online","status_checked_at":"2025-08-30T02:00:09.474Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["ai","data-engineering","embeddings","machine-learning","nlp","vectors"],"created_at":"2024-09-03T00:01:30.340Z","updated_at":"2025-12-14T12:04:52.734Z","avatar_url":"https://github.com/dgarnitz.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n \u003csvg width=\"164\" height=\"164\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\u003e\u003cg filter=\"url(#a)\"\u003e\u003crect x=\"32\" y=\"20\" width=\"100\" height=\"100\" rx=\"16\" fill=\"#1E293B\"/\u003e\u003crect x=\"32.5\" y=\"20.5\" width=\"99\" height=\"99\" rx=\"15.5\" stroke=\"url(#b)\"/\u003e\u003c/g\u003e\u003cpath d=\"m109.645 56.269-6.956-4.02m6.956 4.02v6.887m0-6.887-6.956 4.02m-48.697-4.02 6.957-4.02m-6.957 4.02 6.957 4.02m-6.957-4.02v6.887M81.82 72.34l6.956-4.02m-6.956 4.02-6.957-4.02m6.957 4.02v6.888m0 20.662 6.956-4.019m-6.956 4.02v-6.888m0 6.887-6.957-4.019m0-51.657 6.957-4.016 6.956 4.019m20.87 32.715v6.887l-6.956 4.02m-41.74 0-6.957-4.02v-6.887\" stroke=\"url(#c)\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/\u003e\u003cdefs\u003e\u003cradialGradient id=\"b\" cx=\"0\" cy=\"0\" r=\"1\" gradientUnits=\"userSpaceOnUse\" gradientTransform=\"matrix(50 0 0 50 82 70)\"\u003e\u003cstop offset=\".472\" stop-color=\"#334155\"/\u003e\u003cstop offset=\".764\" stop-color=\"#94A3B8\"/\u003e\u003cstop offset=\"1\" stop-color=\"#334155\"/\u003e\u003c/radialGradient\u003e\u003clinearGradient id=\"c\" x1=\"89.747\" y1=\"31.4\" x2=\"40.821\" y2=\"63.731\" gradientUnits=\"userSpaceOnUse\"\u003e\u003cstop stop-color=\"#F1F5F9\" stop-opacity=\".01\"/\u003e\u003cstop offset=\"1\" stop-color=\"#F1F5F9\"/\u003e\u003c/linearGradient\u003e\u003cfilter id=\"a\" x=\"0\" y=\"0\" width=\"164\" height=\"164\" filterUnits=\"userSpaceOnUse\" color-interpolation-filters=\"sRGB\"\u003e\u003cfeFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"/\u003e\u003cfeColorMatrix in=\"SourceAlpha\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\"/\u003e\u003cfeOffset dy=\"12\"/\u003e\u003cfeGaussianBlur stdDeviation=\"16\"/\u003e\u003cfeColorMatrix values=\"0 0 0 0 0.0588235 0 0 0 0 0.0901961 0 0 0 0 0.164706 0 0 0 0.64 0\"/\u003e\u003cfeBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow_127_2\"/\u003e\u003cfeBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow_127_2\" result=\"shape\"/\u003e\u003c/filter\u003e\u003c/defs\u003e\u003c/svg\u003e\n    \u003ca href=\"https://www.getvectorflow.com/\"\u003e\n        \u003ch1\u003eVectorFlow\u003c/h1\u003e\n    \u003c/a\u003e\n    \u003ch3\u003eOpen source, high-throughput, fault-tolerant vector embedding pipeline\u003c/h3\u003e\n    \u003cspan\u003eSimple API endpoint that ingests large volumes of raw data, processes, and stores or returns the vectors quickly and reliably\u003c/span\u003e\n\u003c/div\u003e\n\u003ch4 align=\"center\"\u003e\n  \u003ca href=\"https://discord.gg/MEXuahMs2F\"\u003eJoin our Discord\u003c/a\u003e  |\n  \u003ca href=\"https://www.getvectorflow.com/\"\u003eWebsite\u003c/a\u003e  |  \n  \u003ca href=\"mailto:dan@getvectorflow.com\"\u003eGet in touch\u003c/a\u003e |\n  \u003ca href=\"https://vectorflow.dev-docs.dev/docs/\"\u003eDocs\u003c/a\u003e |\n  \u003ca href=\"https://app.getvectorflow.com/\"\u003eFree Hosted Version\u003c/a\u003e \n\u003c/h4\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/aQOlOT14DaA/0.jpg)](https://www.youtube.com/watch?v=aQOlOT14DaA)\n\n\u003c/div\u003e\n\n# Introduction\n\nVectorFlow is an open source, high throughput, fault tolerant vector embedding pipeline. With a simple API request, you can send raw data that will be chunked, embedded and stored in any vector database or returned back to you.  \n\nThis current version is an MVP. We recommend using it with Kubernetes in production (see below for details). For text-based files, it supports TXT, PDF, HTML and DOCX. \n\n# Run it Locally\nWith three commands you can run VectorFlow locally:\n```\ngit clone https://github.com/dgarnitz/vectorflow.git\ncd vectorflow\n./setup.sh\n```\n\n#### Embed Documents with Client\nTo start embedding documents locally, [install the VectorFlow Client python library](https://pypi.org/project/vectorflow-client/) in your python application's virtual environment. \n```\npip install vectorflow-client\n```\nthen run the following\n```\nfrom vectorflow-client.client.vectorflow import Vectorflow\n\nvectorflow = Vectorflow()\nvectorflow.embeddings_api_key = os.getenv(\"OPEN_AI_KEY\")\npaths = ['path_to_your_file1', 'path_to_your_file2', ...]\nresponse = vectorflow.upload(paths)\n```\n\nYou do **not** need to clone the VectorFlow repo to utilize the client functionality via pip. For more instructions see the `README.md` in the `client` directory.\n\nSee the appendix for details on how to use the `testing_clients` scripts.\n\n## Docker-Compose\n\nThe best way to run VectorFlow is via `docker compose`. If you are running this on Mac, please grant Docker permissions to read from your Documents folder [as instructed here](https://stackoverflow.com/questions/58482352/operation-not-permitted-from-docker-container-logged-as-root). If this fails, remove the `volume` section from the `docker-compose.yml`.\n\n### 1) Set Environment Variables\n\nFirst create a folder, `env_scripts`, in the root for all the environment variables, then create `env_vars.env` in the `env_scripts` folder to add all the environment variables mentioned below. You only need to set the `LOCAL_VECTOR_DB` variable if you are running qdrant, Milvus or Weaviate locally.  \n\n```\nINTERNAL_API_KEY=your-choice\nPOSTGRES_USERNAME=postgres\nPOSTGRES_PASSWORD=your-choice\nPOSTGRES_DB=vectorflow\nPOSTGRES_HOST=postgres\nRABBITMQ_USERNAME=guest\nRABBITMQ_PASSWORD=guest\nRABBITMQ_HOST=rabbitmq\nLOCAL_VECTOR_DB=qdrant | weaviate\nAPI_STORAGE_DIRECTORY=/tmp\nMINIO_ACCESS_KEY=minio99\nMINIO_SECRET_KEY=minio123\nMINIO_ENDPOINT=minio:9000\nMINIO_BUCKET=vectorflow\n```\n\nYou can choose a variable for `INTERNAL_API_KEY`, `POSTGRES_PASSWORD`, and `POSTGRES_DB`, but they must be set.\n\n### 2) Run Docker-Compose\n\nMake sure you pull Rabbit MQ, Postgres, Min.io into your local docker repo. We also recommend running a vector DB in locally, so make sure to pull the image of the one you are using. Our `docker-compose` file will spin up qdrant by default and create two index/collections. If you plan to run Milvus or Weaviate, you will have to configure them on your own. \n\n```\ndocker pull rabbitmq\ndocker pull postgres\ndocker pull qdrant/qdrant | docker pull semitechnologies/weaviate\ndocker pull minio/minio\n```\n\nThen run:\n\n```\ndocker-compose build --no-cache\ndocker-compose up -d\n```\n\nNote that the `init` containers are running a script that sets up the database schema, vector DB and Min.io object store. These containers stop after the script completes. For qdrant, make sure to pull version 1.9.1 since that is the version the qdrant client python package is supposed to work with. \n\n\n## Using VectorFlow\n\nThe best way to use VectorFlow is with the python client. \n\nTo use VectorFlow for development, make an HTTP request to your API's URL - for example, `localhost:8000` from your development machine, or `vectorflow_api:8000` from within another docker container.\n\n### Request \u0026 Response Payload\n\nAll requests require an HTTP Header with `Authorization` key which is the same as your `INTERNAL_API_KEY` env var that you defined before (see above). You must pass your vector database api key with the HTTP Header `X-VectorDB-Key` if you are running a connecting to a cloud-based instance of a vector DB, and the embedding api key with `X-EmbeddingAPI-Key` if you are using OpenAI. HuggingFace Sentence Transformer embeddings do not require an api key, but you must follow the above steps to run the container with the model you need. \n\nVectorFlow currently supports Pinecone, Qdrant and Weaviate vector databases. \n\n#### Embed a Single File\nTo submit a single file for embedding, make a `POST` request to the `/embed` endpoint with a file attached, the `'Content-Type: multipart/form-data'` header and the following payload:\n\n```\n{\n    'SourceData=path_to_txt_file'\n    'LinesPerBatch=4096'\n    'EmbeddingsMetadata={\n        \"embeddings_type\": \"OPEN_AI\",\n        \"chunk_size\": 512,\n        \"chunk_overlap\": 128,\n        \"chunk_strategy\": \"EXACT | PARAGRAPH | SENTENCE | CUSTOM\",\n        \"model\": \"text-embedding-3-small | text-embedding-3-large | text-embedding-ada-002\"\n    }'\n    'VectorDBMetadata={\n        \"vector_db_type\": \"PINECONE | QDRANT | WEAVIATE\",\n        \"index_name\": \"index_name\",\n        \"environment\": \"env_name\"\n    }'\n    'DocumentID=your-optional-internal-tracking-id'\n}\n```\n\nThis will create a `job` and you will get the following payload back:\n\n```\n{\n    'message': f\"Successfully added {batch_count} batches to the queue\",\n    'JobID': job_id\n}\n```\n\nRight now this endpoint only supports uploading single files at a time, up to 25 MB due to timeout issues. Note that it may be deprecated.\n\n#### Embed Multiple Files At Once\nTo submit multiple files for embedding, make a `POST` request to the `/jobs` endpoint. The payload is the same as for single file embedding except the way you attach multiple files is different:\n\n```\n{\n    'files=[\n        ('file',  ('test_pdf.pdf', open(file1_path, 'rb'), 'application/octet-stream')),\n        ('file', ('test_medium_text.txt', open(file2_path, 'rb'), 'application/octet-stream'))\n    ]'\n}\n```\n*NOTE:* You must `stream` the files to the endpoint, not send it as a conventional post request or it will fail. \n\nThis endpoint will create one `job` per file uploaded. You will get the following JSON payload back:\n\n```\n{   \n    'successful_uploads': successfully_uploaded_files,\n    'failed_uploads': failed_uploads,\n    'empty_files_count': empty_files_count,\n    'duplicate_files_count': duplicate_files_count\n}\n```\n\nWhere `successfully_uploaded_files` is a list of tuples containing `(file name, job id)` and `failed_uploads` is a list of file names that failed to upload so you can retry them. \n\n#### Get a Single Job Status\nTo check the status of a `job`, make a `GET` request to this endpoint: `/jobs/\u003cint:job_id\u003e/status`. The response will be in the form:\n\n```\n{\n    'JobStatus': job_status\n}\n```\n\n#### Get Multiple Job Statuses\nTo check the status of multiples `job`, make a `POST` request to this endpoint: `/jobs/status`. The request body will be in the form:\n\n```\n{\n    'JobIDs': job_ids\n}\n```\n\nand the response will be in the form\n```\n{\n    'Jobs': [{'JobID': job_id, 'JobStatus': job_status}, ...]}\n```\nThere is an example in `testing_clients/get_jobs_by_ids.py`.\n\n### Vector Database Standard Metadata Schema \nVectorFlow enforces a standardized schema for uploading data to a vector store:\n```\nid: string\nsource_data: string\nsource_document: string\nembeddings: float array\n```\n\nThe id can be used for deduplication and idempotency. Please note for Weaviate, the id is called `vectorflow_id`. \n\nWe plan deprecicate this in the near futuer to support dynamically detected and/or configurable schemas down the road. \n\n### Chunking Schema \u0026 Custom Chunking\nVectorFlow's built in chunkers count by token not by character. A `chunk` in vectorflow is a dictionary that has the following keys:\n```\ntext: str\nvector: list[float]\n```\n\nYou may run a custom chunker by adding a file, `custom_chunker.py`, with a method, `chunker(source_data: list[str])` to the `src/worker` directory prior to build the docker image for the worker. This chunker must return a list of `chunk` dictionaries that conform to the standard above. \n\nYou can add any keys you want to the `chunk` dictionary as long as its _JSON serializable_, meaning no custom classes or function, datetimes types or circular code references. You can use this custom chunk to then upload metadata to the vector DB with whatever schema you desire. \n\n### Raw Embeddings Webhook\nIf you wish to use VectorFlow only for chunking and generating embeddings, pass a `WebhookURL` parameter in the body of the `/embed` request and a `X-Webhook-Key` as a header. VectorFlow assumes a webhook key is required for writing back to any endpoint. The embeddings are sent back along with the source chunks in the `chunk` dictionary outlined above. This is sent as json with the following form:\n```\n{\n    'Embeddings': list[dict],\n    'DocumentID': str,\n    'JobID': int\n}\n```\n\n### Chunk Validation Webhook\nIf you wish to validate which chunks you wish to embed, pass a `ChunkValidationURL` parameter in the body of the `/embed` request. This will send the request with the following json payload, `{\"chunks\": chunked_data}`, where `chunked_data` is a list of `chunk` dictionaries. It will expected back json containing key `valid_chunks` with a list of valid chunks for embedding. This endpoint will timeout after 30 seconds by default but can be configured in the application code. \n\n### S3 Endpoint\nVectorFlow is integrated with AWS s3. You can pass a pre-signed s3 URL in the body of the HTTP instead of a file. Use the form field `PreSignedURL` and hit the endpoint `/s3`. This endpoint has the same configuration and restrictions as the `/embed` endpoint. \n\n### Telemetry\nVectorFlow uses PostHog to anonymously collect data about usage. This does not collect any personally identifiable information. If you want to disable it though, add the following enviroment variable to your `env_vars.env`:\n```\nTELEMETRY_DISABLED=True\n```\n\n## Kubernetes\nYou can run VectorFlow locally in Kubernetes with minikube using `./kube/scripts/deploy-local-k8s.sh`, which will apply all the yaml files located in `kube/`. This script will not work if you have not installed docker, minikube and kubectl. \n\nThis script will first build the images locally, then transfer them into minikube. If you want to check what images are available in minikube, run the following:\n\n```\neval $(minikube docker-env)\ndocker images\n```\n\nYou will need to run `minikube tunnel` to access the resources located in the cluster from your development machine. The setup script will load the images from your local docker context into minikube's. \n\nYou can use the yaml files in `kube/` as a basis for a production deployment but you will need to customize slightly to the needs of your specific cluster. **Contact us if you need help.**\n\n# Contributing\n\nWe love feedback from the community. If you have an idea of how to make this project better, we encourage you to open an issue or join our Discord. Please tag `dgarnitz` and `danmeier2`.\n\nOur roadmap is outlined in the section below and we would love help in building it out. Our open issues are a great place to start and can be viewed [here](https://github.com/dgarnitz/vectorflow/issues). If you want to work on something not listed there, we recommend you open an issue with a proposed approach in mind before submitting a PR.\n\nPlease tag `dgarnitz` on all PRs and *update the README* to reflect your changes.\n\n### Testing\n\nWhen submitting a PR, please add units tests to cover the functionality you have added. Please re-run existing tests to ensure there are no regressive bugs. Run from the `src` directory. To run an individual test use:\n\n```\npython -m unittest module.tests.test_file.TestClass.test_method\n```\n\nTo run all the tests in the file use: \n```\npython -m unittest module.tests.test_file\n```\n\nFor end-to-end testing, it is recommend to build and run using the docker-compose, but take down the container you are altering and run it locally on your development machine. This will avoid the need to constantly rebuild the images and re-run the containers. Make sure to change the environment variables in your development machine terminal to the correct values (i.e. `localhost` instead of `rabbitmq` or `postgres`) so that the docker containers can communicate with your development machine. Once it works locally you can perform a final test with everything in docker-compose.\n\n### Verifying\nPlease verify that all changes work with docker-compose before opening a PR. \n\nWe also recommend you add verification evidence, such as screenshots, that show that your code works in an end to end flow. \n\n\n# Roadmap\n\n- [ ] Support for multi-file, directory data ingestion from sources such as Salesforce, Google Drive, etc\n- [ ] Retry mechanism\n- [ ] Langchain integrations\n- [ ] Support callbacks for writing object metadata to a separate store\n- [ ] Dynamically configurable vector DB schemas\n- [ ] Deduplication capabilities\n- [ ] Vector version control\n- [ ] \"Smart\" chunker\n- [ ] \"Smart\" metadata extractor\n\n# Appendix\n\n## Embed with Testing Scripts\nOne easy way to use VectorFlow is with the our testing clients, located in `testing_clients/` directory. There are several scripts, with different configurations for qickly uploading data. We recommmend starting with the `testing_clients/standard_upload_client.py` - Running this script will submit a single document to VectorFlow for embedding with Open AI ADA and upload to the local qdrant instance. You can change the values to match your configuration. To upload multiple files at once, use the `testing_clients/streaming_upload_client.py`\n\nNote that the `TESTING_ENV` variable is the equivalent of the `environment` field in the `VectorDBMetadata`, which corresponds to an environment in Pincone, a class in Weaviate, a collection in qdrant, etc. \nThe `testing_clients` directory has sample scripts you can follow to run vectorflow. Add your embedding and database keys to the `env_scrips/env_vars.sh` script that was generated and set the `filepath` variable in `testing_clients/standard_upload_client.py` to point to the file you want to embed. Then run:\n```\nsource env_scrips/env_vars.sh\npython testing-clients/standard_upload_client.py\n```\n\nTo upload multiple files at once, use the `testing_clients/streaming_upload_client.py`\n\nSee above for a more detailed description of how to manually set up and configure the system. Please note that the `setup` script will not create a development environment on your machine, it only sets up and runs the docker-compose. We do not advise using VectorFlow on Windows. \n\n### Request\nTo perform a search, send a `POST` request to `/images/search` endpoint with an image file attached, the `'Content-Type: multipart/form-data'` header and the following body:\n```\n{\n    'ReturnVectors': boolean,\n    'TopK': integer, less than 1000,\n    'VectorDBMetadata={\n        \"vector_db_type\": \"PINECONE | QDRANT | WEAVIATE\",\n        \"index_name\": \"index_name\",\n        \"environment\": \"env_name\"\n    }'\n}\n```\nAll requests require an HTTP Header with `Authorization` key which is the same as your `INTERNAL_API_KEY` env var that you defined before (see above). You must pass your vector database api key with the HTTP Header `X-VectorDB-Key` if you are running a connecting to a cloud-based instance of a vector DB. \n\n### Response\nAn image similarity search will return a response object containing the top K matches, plus the raw vectors if requested, with of the following form:\n```\n{\n    \"similar_images\": list of match objects\n    \"vectors\": list of list of floats\n}\n```\nwhere `match`` objects are defined as:\n```\n{\n    \"id\": str,\n    \"score\": float,\n    \"metadata\": {\"source_document\" : str}\n}\n```\n\n### Building the Individual Images with Docker Commands\nIf you want to use `docker build` and `docker run` to build and run individual images instead of `docker-compose` follow these steps:\n1. `cd src/`\n2. `docker build --file api/Dockerfile -t vectorflow_api:latest .` to build - don't forget the period at the end\n3. `docker run --network=vectorflow --name=vectorflow_api -d --env-file=../env_scripts/env_vars.env -p 8000:8000 vectorflow_api:latest` to run the api. you don't need the port argument to run the worker","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgarnitz%2Fvectorflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdgarnitz%2Fvectorflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdgarnitz%2Fvectorflow/lists"}