When I decided to write a training article on V, I initially had no specific idea in mind. After some consideration, I decided to combine the article with the V community itself by developing a utility that displays the top repositories on V based on the number of stars they have on GitHub. This will help identify the most popular repositories and contributors within the V community.
Of course, the V language and projects by the V organization will be included in the leaderboards, but I still wonder who was able to accumulate more stars outside the language organization.
Installing V
If you haven’t installed V yet, then follow the instructions from the Installation article from documentation.
Creating a project
Let us create a new project, V provides the handy v new
command for this:
v new stars
The command will ask you to provide additional information about the project, which you can skip
by pressing Enter
.
As a result, the command will create a new folder stars
and add several files to it:
cd stars
tree .
# .
# ├── src
# │ └── main.v
# └── v.mod
#
# 2 directories, 2 files
Let us check that everything is fine by running our project:
v run .
# Hello, World!
Fetching
I have already prepared the URL from which we can fetch the data. You can open it in your browser and view the JSON output: https://api.github.com/search/repositories?sort=stars&order=desc&q=language:v
GitHub returns JSON with the total number of repositories, and the items
field contains an array
of repositories that we need.
It’s already pre-sorted by stars in descending order because we specified that in the part
sort=stars&order=desc
of request in the URL.
Now, our task is simply to fetch the data from this URL and output it to the terminal.
Open the file src/main.v
in your favorite editor or IDE.
You can see the available plugins for your editor in
documentation.
In this article, we will use the JetBrains IDE with the IntelliJ V plugin, as this bundle provides the best V development experience.

In order to fetch the list of repositories, we need the
net.http
module.
To make a simple GET request, we can use the get()
method,
which takes a request URL as a parameter.
Let us import this module. You can read more about imports in documentation.
import net.http
Next, add a constant with GitHub URL:
const github_repositories_url = 'https://api.github.com/search/repositories?sort=stars&order=desc&q=language:v'
Remove the current code from the main()
function and add a http.get()
call to fetch the data
from the URL, and output the response body.
fn main() { response := http.get(github_repositories_url)! println(response.body) }
Since http.get()
returns the
Result,
we must either
handle
the error case or
propagate
it up.
If you propagate an error in the
main()
function, the program will panic because it is not possible to propagate the error further up the call stack.
As a result, we will get the following code:
module main import net.http const github_repositories_url = 'https://api.github.com/search/repositories?sort=stars&order=desc&q=language:v' fn main() { response := http.get(github_repositories_url)! println(response.body) }
Try to execute it using the v run .
and look at the result.
JSON magic
From the GitHub response, we need only two fields, total_count
and items
.
From items
we need not all fields, only full_name
, description
, stargazers_count
,
and html_url
.
The
json
module does not require describing all fields,
we can specify only the necessary fields, and the rest will be ignored.
The json.decode()
method accepts a structure that will be built during the parsing process and
a string with JSON; in our case, it is the response.body
.
So let us describe this
structure.
As we decided earlier, we only need total_count
and items
:
struct GitHubRepositoriesSearchAPI { pub: total_count int items []GitHubRepositoriesItem }
items
— is an array of structures, so we also need to provide a structure for it:
struct GitHubRepositoriesItem { pub: full_name string description string stargazers_count int html_url string }
These are all the structures we need to describe the JSON response from GitHub. We only need to parse the response into a structure.
Add the following code after response := http.get(github_repositories_url)!
:
repositories_result := json.decode(GitHubRepositoriesSearchAPI, response.body) or { panic('An error occurred during JSON parsing: ${err}') }
In the code above, you may notice the variable err
, which no one has declared before.
This is a special variable that is defined in the or
block, which contains the error that
was returned from the function.
The or
block and the err
variable are syntax sugar for unwrapping the Result or the Option type,
you can read more about it in
documentation.
Once we have the structure, we can work with the data the way we are used to in V. For example, to output the total number of repositories in V, we can add the following code:
println('The total repository count is ${repositories_result.total_count}')
V supports string interpolation, which allows us to include variables or expressions directly in strings. This feature makes it easy to format strings.
Make sure you have written everything correctly and run the code using the v run .
command.

Let us display the list of repositories.
Display everything beautifully
All we need to do is iterate over the items
array and output information about the repositories.
V provides a
for loop
for this, which makes it easy to iterate through all the elements of the array.
for index, repository in repositories_result.items { // ... }
If we do not need an index
, we can simply omit it.
Now we need to display everything beautifully. But we will do it beautifully in the truest sense of the word. Let us not complicate this article by searching for a suitable module. I chose everything in advance. For color text output in the terminal, we will use the Mewzax.chalk module.
The standard library already contains the
term
module, which allows you to display colored text in the terminal, but I thought it would be more interesting to show how to use a third-party module.
Let us use the built-in package manager V to install it:
v install Mewzax.chalk
You can find the module README here.
Now import it:
import mewzax.chalk
And write the formatted output of repositories inside the body of the for
loop:
for index, repository in repositories_result.items { colored_description := chalk.fg(repository.description, 'cyan') colored_star_count := chalk.fg(repository.stargazers_count.str(), 'green') println('#${index + 1} ${repository.full_name}') println(' URL: ${repository.html_url}') if repository.description != '' { println(' Description: ${colored_description}') } println(' Star count: ${colored_star_count}') }
The if repository.description != ''
condition was added in case there is no description in
the repository, so we don’t output an empty string.
Run the code and look at the result.

Conclusion
From the obtained results, we can conclude that the top 3 projects on V by stars are now:
- cotowali/cotowali – A statically typed scripting language that transpiles into POSIX sh.
- nedpals/vex – Easy-to-use, modular web framework built for V.
- elliotchance/vsql – Single-file or PostgreSQL-server compatible transactional SQL database written in pure V.
Homework
- Try using search filters or the GitHub code to exclude V organization repositories so that you can only see community projects.
- Create a separate function for fetching data from the GitHub API, where the sorting type and order can be passed as arguments.
You can ask questions or share the results of your work in the comments below, or in Discord.
Source code: https://github.com/vlang-association/v-tutorial-stars