Our Blog

Ongoing observations by End Point Dev people

DevOps & Kubernetes engineer job opening

Jon Jensen

By Jon Jensen
November 4, 2021

dumpster with worn sticker warning against sleeping or falling

We are looking for a full-time, salaried DevOps / Kubernetes engineer to work on cloud hosting projects with our clients and our internal hosting team.

End Point Dev is an Internet technology consulting company based in New York City, with 50 employees serving many clients ranging from small family businesses to large corporations. We are going strong after 26 years in business!

Even before the pandemic most of us worked remotely from home offices. We collaborate using SSH, Git, project tracking tools, Zulip chat, video conferencing, and of course email and phones.

What you will be doing:

  • Automate, set up, support, and maintain complex containerized applications in the cloud.
  • Audit and improve security, backups, reliability, monitoring.
  • Work together with End Point Dev co-workers and our clients’ in-house staff.
  • Use your desktop operating system of choice: Linux, macOS, or Windows.
  • Work with open source software and contribute back as opportunity arises.

You’ll need professional experience with:

  • Production Kubernetes administration on Amazon EKS (2+ years)
  • Linux and common distributions including Ubuntu, RHEL/​CentOS
  • Public clouds such as AWS, GCP, Azure, Linode, DigitalOcean
  • Containerization with Docker and/or Podman
  • IaC tools such as Terraform, CloudFormation, Ansible, Chef, Puppet, Salt
  • CI/CD pipelines, release management
  • Git version control, GitHub or GitLab
  • Scripting and programming with bash, Python, Ruby, Go, etc.
  • OS fundamentals, networking, and firewalls
  • HTTP, REST APIs

You have these important work traits:

  • Strong verbal and written communication skills
  • An eye for detail
  • Tenacity in solving problems and focusing on customer needs
  • A feeling of ownership of your projects
  • Work both independently and as part of a team

What work here offers:

  • Collaboration with knowledgeable, friendly, helpful, and diligent co-workers around the world
  • Freedom from being tied to an office location
  • Flexible, sane work hours
  • Paid holidays and vacation
  • Annual bonus opportunity
  • (For U.S. employees:) Health insurance subsidy and 401(k) retirement savings plan

Get in touch with us:

Please email us an introduction to [email protected] to apply. Include your location, a resume/​CV, your Git repository or LinkedIn URLs, and whatever else may help us get to know you.

We look forward to hearing from you! Direct work seekers only, please—​this role is not for agencies or subcontractors.

We are an equal opportunity employer and value diversity at our company. We do not discriminate on the basis of sex/​gender, race, religion, color, national origin, sexual orientation, age, marital status, veteran status, or disability status.


jobs kubernetes devops remote-work

Java developer job opening

Jon Jensen

By Jon Jensen
November 3, 2021

Person on boulder overlooking valley with lake

We are seeking a full-time Java server-side software developer based in the United States to work with us on our clients’ applications.

End Point Dev is an Internet technology consulting company based in New York City, with 50 employees serving many clients ranging from small family businesses to large corporations. The company is going strong after 26 years in business!

Even before the pandemic most of us worked remotely from home offices. We collaborate using SSH, Git, project tracking tools, Zulip chat, video conferencing, and of course email and phones.

What you will be doing:

  • Develop new web applications and support existing ones for our clients.
  • Work together with End Point Dev co-workers and our clients’ in-house staff.
  • Use your desktop operating system of choice: Linux, macOS, or Windows.
  • Enhance open source software and contribute back as opportunity arises.

You’ll need professional development experience with:

  • 4+ years of development with Java for server-side applications
  • Frameworks and libraries such as Wildfly, Hibernate, Spring, Struts, Play
  • Databases such as PostgreSQL, Redis, Solr, Elasticsearch, etc.
  • Security consciousness, such as under HIPAA for safe medical & PII data handling
  • Git version control
  • Automated testing
  • HTTP, REST APIs

You have these important work traits:

  • Strong verbal and written communication skills
  • An eye for detail
  • Tenacity in solving problems and focusing on customer needs
  • A feeling of ownership of your projects
  • Work both independently and as part of a team
  • A good remote work environment

For some of our clients you will need to submit to and pass a criminal background check.

What work here offers:

  • Collaboration with knowledgeable, friendly, helpful, and diligent co-workers around the world
  • Freedom from being tied to an office location
  • Flexible, sane work hours
  • Paid holidays and vacation
  • Health insurance subsidy and 401(k) retirement savings plan
  • Annual bonus opportunity

Get in touch with us:

Please email us an introduction to [email protected] to apply. Include your location, a resume/​CV, your Git repository or LinkedIn URLs, and whatever else may help us get to know you.

We look forward to hearing from you! Direct work seekers only, please—​this role is not for agencies or subcontractors.

We are an equal opportunity employer and value diversity at our company. We do not discriminate on the basis of sex/​gender, race, religion, color, national origin, sexual orientation, age, marital status, veteran status, or disability status.


jobs java remote-work

Rails developer job opening

Jon Jensen

By Jon Jensen
November 3, 2021

Two software developers at their computers Photo by WOCinTech Chat, CC BY 2.0, cropped

We are seeking a full-time Ruby on Rails software developer based in the United States to work with us on our clients’ applications.

End Point Dev is an Internet technology consulting company based in New York City, with 50 employees serving many clients ranging from small family businesses to large corporations. The company is going strong after 26 years in business!

Even before the pandemic most of us worked remotely from home offices. We collaborate using SSH, Git, project tracking tools, Zulip chat, video conferencing, and of course email and phones.

What you will be doing:

  • Develop new web applications and support existing ones for our clients.
  • Work together with End Point Dev co-workers and our clients’ in-house staff.
  • Use your desktop operating system of choice: Linux, macOS, or Windows.
  • Enhance open source software and contribute back as opportunity arises.

You’ll need professional development experience with:

  • 4+ years of development with Ruby on Rails
  • JavaScript frameworks and libraries such as Vue.js, React, Angular
  • Databases such as PostgreSQL, Redis, Solr, Elasticsearch, etc.
  • Security consciousness, such as under HIPAA for safe medical & PII data handling
  • Git version control
  • Automated testing
  • HTTP, REST APIs

You have these important work traits:

  • Strong verbal and written communication skills
  • An eye for detail
  • Tenacity in solving problems and focusing on customer needs
  • A feeling of ownership of your projects
  • Work both independently and as part of a team
  • A good remote work environment

For some of our clients you will need to submit to and pass a criminal background check.

What work here offers:

  • Collaboration with knowledgeable, friendly, helpful, and diligent co-workers around the world
  • Freedom from being tied to an office location
  • Flexible, sane work hours
  • Paid holidays and vacation
  • Health insurance subsidy and 401(k) retirement savings plan
  • Annual bonus opportunity

Get in touch with us:

Please email us an introduction to [email protected] to apply. Include your location, a resume/​CV, your Git repository or LinkedIn URLs, and whatever else may help us get to know you.

We look forward to hearing from you! Direct work seekers only, please—​this role is not for agencies or subcontractors.

We are an equal opportunity employer and value diversity at our company. We do not discriminate on the basis of sex/​gender, race, religion, color, national origin, sexual orientation, age, marital status, veteran status, or disability status.


jobs ruby rails remote-work

Generating TOTP QR codes as Unicode text from the command line

Bharathi Ponnusamy

By Bharathi Ponnusamy
October 28, 2021

banner, qr code, Unicode, text, security, console, terminal, command line

(QR = “Quick Response” — good to know!)

Python’s QR code generator library qrcode generates QR codes from a secret key and outputs to a terminal using Unicode characters, not a PNG graphic as most other libraries do. We can store that in a text file. This is a neat thing to do, but how is this functionality useful?

Benefits of having Unicode QR code as a text file:
  • Storing the QR code as a text file takes less disk space than a PNG image.
  • It is easy to read the QR code over ssh using the cat command; you don’t even have to download the file to your own workstation.
  • It is simpler to manage QR codes in Git as text files than as PNG images.

This can be used for any kind of QR code, but we have found it especially useful for managing shared multi-factor authentication (MFA, including 2FA for 2-factor authentication) secrets for TOTPs (Time-based One-Time Passwords).

Multi-factor authentication (MFA)

Many services provide a separate account and login for each user so that accounts do not need to be shared, and thus passwords and multi-factor authentication secrets do not need to be shared either. This is ideal, and what we insist on for our most important accounts.

Unfortunately, however, some services provide only a single login per account, or only a single primary account login with the other accounts being limited in serious ways (no access to billing, account management, etc.) so that any business relying on them needs to share the access between several authorized users. A single point of failure in an account login is a serious problem when that one person is unavailable.

TOTP mobile apps

There are many good mobile apps for managing TOTP keys and codes, including Aegis, FreeOTP, Google Authenticator, and many others. Look for one that works with no connection to the outside world, so that you won’t be stuck when off internet & data networks.

Most applications support scanning QR codes with the phone’s camera, or else typing in a secret key to import the accounts.

For those shared accounts with no option for fully empowered individual user accounts, we can convert secret keys into QR codes for easy sharing and easy imports.

First, note that you should never use online QR code generators for MFA secrets! You risk exposing your extra authentication factors and defeating the purpose of your extra work.

Python’s ‘qrcode’ library

The qrcode Python library provides a qr executable that can print your QR code using UTF-8 characters on the console.

Installation

apt install python3-qrcode

Or visit https://pypi.org/project/qrcode/

The contents of the QR code are a URL in the format:

otpauth://totp/{username}?secret={key}&issuer={provider_name}

The provider_name can contain spaces; however, they need to be URL-encoded and entered as %20 for auth to work correctly on iOS. Otherwise, an invalid barcode error will be shown when adding the code.

For example, if you generate the QR code with key JSZE5V4676DZFCUCFW4GLPAHEFDNY447 for the account [email protected], the resulting command would be:

$ qr "otpauth://totp/Example:[email protected]?secret=JSZE5V4676DZFCUCFW4GLPAHEFDNY447&issuer=Superhost" 

Here’s what its output looks like:

qrcode

Providing the username and issuer will display it properly in the list of configured accounts in your authenticator application. For example: Superhost (Example:[email protected])

Reference


security unicode

.NET Conf 2021 is coming!

Juan Pablo Ventoso

By Juan Pablo Ventoso
October 27, 2021

.NET Conf 2021 is coming!

It’s that time of the year again! It has been almost one year since .NET 5 was launched at .NET Conf 2020, unifying .NET Framework and .NET Core into a single open-source and cross-platform framework. With .NET 6 around the corner, it’s time to prepare for the new edition, .NET Conf 2021, starting on November 9th.

This edition will be the 11th online conference, and the Agenda will mainly focus on the .NET 6 launch and the new C# 10, along with some coding challenges and community sessions. The event is organized by both the .NET community and Microsoft. The main changes that will likely be discussed at the conference, based on what we’ve seen through the previews, might include:

Mobile development

We will see several changes to how web mobile app development works under .NET 6. With a smaller, optimized, and optional SDK for mobile based on Xamarin, now called Multi-platform App UI or MAUI, developing an app that targets multiple mobile platforms should be simpler than ever.

.NET 6 and MAUI

Hot reload (after some struggling)

The Hot Reload feature, which will allow us to make and apply changes to the code at execution time, will be finally available in .NET 6. There was some noise about it in the past days since Microsoft made a decision to lock it to Visual Studio 2022, which is a Windows-limited mostly-paid product. But after the open source community made it clear they were angry about it, Microsoft reversed the change and the feature will be available for all platforms.

Blazor 6

The new version of Blazor will also have improvements. One of the main features is the implementation of ahead-of-time compilation, that allows generating WebAssembly code during the publishing process. That way, the application performance is increased, since it can run natively instead of needing a .NET IL interpreter.

LTS (Long Term Support)

.NET 6 is a Long Term Support version, which means that it will have support for at least 3 years after its release. The current version, .NET 5, is a General Availability (GA) version, which means its support will likely end six months after the next release is available.

Several improvements were introduced to different aspects of the framework, including AOT compilation or the Minimal API Framework. There are also improvements to the build speed as we can see in the chart below. A complete list of breaking changes can be seen here.

.NET 5 vs. .NET 6 build improvements

Bonus: Although not part of the event itself, the new version of Visual Studio will also be available from November 8th, and it will be launched on an online event that Microsoft is preparing with several presentations from the development team.

As we did last year, the .NET team at End Point Dev will be listening to the talks and presentations from the conference, and trying out the new features that will be publicly available on November 9th. Exciting days ahead! We hope to see you there.


dotnet windows conference

Moving to EndPointDev.com

Rick Peltzman

By Rick Peltzman
October 21, 2021

scene of seashore, palm trees, bridges, old stone walls, grass

Hello to all our cherished clients and friends. I am excited to make an announcement!

End Point has changed our domain name from EndPoint.com to EndPointDev.com.

While our official legal name remains End Point Corporation, we are also updating our branding to match our new domain name. You will notice on our website that we are now referring to ourselves as End Point Dev, the “Dev” being short for “development.”

There are many companies named End Point and there has been a little confusion about this over the years. None of the other End Points (or “Endpoints”) do the type of development work that we do. They range from a utility company to a title insurance company to a medical lab services company and beyond. In our quest to separate ourselves and distinguish who we are, we are transitioning to EndPointDev.com.

From now on you will receive email from, and send email to, your contacts here with their new suffix-adjusted domain names, e.g., instead of [email protected]endpoint.com use [email protected]. After December 1, 2021, expect your emails to bounce back if you do not use the new and correct email address.

This change also holds true for our group/​alias addresses that you may be using, such as [email protected]endpoint.com, [email protected]endpoint.com, etc., which are now [email protected], [email protected], etc.

At End Point Dev we have expanded our services, capabilities, and expertise greatly in recent years. Our capabilities range from ecommerce to 3D visualization platforms, from database to AI and other applications development, from cloud devops and hosting services to critically needed EpiTrax disease tracking and tracing for states throughout the U.S.

We believe that this rebranding effort will help distinguish us, but it will require a bit of housekeeping. So please update your email address books and web browser bookmarks. Thank you!


company

Job opening: Systems Programmer

Matt Vollrath

By Matt Vollrath
October 13, 2021

foggy autumn mountain view

End Point is an Internet technology company with headquarters in New York City and an office in Johnson City, Tennessee. The majority of our 50 employees work remotely. We provide consulting, development, and support services to many clients ranging from small family businesses to large corporations. We also develop and support an immersive visualization product called Liquid Galaxy.

Job Description

We are looking for a C++ developer to join our team full-time to develop new custom software solutions and improve existing ones for our clients. The person in this position will work collaboratively with our talented team of developers to design, implement, test, debug, and maintain systems software.

Responsibilities

  • Create reusable, effective, secure, and scalable C++ code.
  • Translate technical requirements into code.
  • Identify bottlenecks and bugs in the system and develop solutions.
  • Troubleshoot and ensure that software applications are running correctly.

Skills and Qualifications

  • English language proficiency
  • Preferably based in the United States
  • Strong technical and communication skills
  • 4+ years of professional experience developing software using C++
  • Proficiency with containers, networking fundamentals, and pub-sub messaging systems such as ROS, ROS2, Socket.IO
  • Experience programming in Python and JavaScript/​TypeScript for Node.js and browser, or equivalent
  • Strong experience writing modules for high-level languages such as Python, Node
  • Good understanding of code versioning tools and proficiency with Git
  • Proficient with Linux including shell scripting
  • Ideally also experience with database/​interface architecture and design, the Unity engine, and/or WebRTC

Benefits

  • Flexible, sane work hours
  • Annual bonus opportunity
  • Paid holidays and vacation
  • Health insurance subsidy
  • 401(k) retirement savings plan

How to contact us

Please email us an introduction to [email protected] to apply. Include your location, your resume/​CV, your LinkedIn URL (if you have one), and whatever else helps us get to know you.

We look forward to hearing from you! Direct employment seekers only, please—​this role is not for agencies or subcontractors.

Equal opportunity employer

We are an equal opportunity employer and value diversity at our company. We do not discriminate on the basis of sex/​gender, race, religion, color, national origin, sexual orientation, age, marital status, veteran status, or disability status.


jobs remote-work

Vue GraphQL integration using Apollo Client

By Daniel Gomm
October 8, 2021

Photo by Mathew Benoit on Unsplash

Introduction

In this post I’ll go over everything you need to know to get your Vue app using GraphQL to send and receive data. This post only covers the frontend — stay tuned for my next post on making a GraphQL server using Django and graphene-python!

For the uninitiated: GraphQL is a query language that aims to replace the traditional REST API. The idea is that, instead of having separate endpoints for each resource in your API, you use one endpoint that accepts GraphQL queries and mutations for all of your resources. Overall, this makes data access on the frontend more like querying a database. Not only does it give you more control over your data, but it also can be much faster than using a REST API, providing a better user experience.

Getting started

To get your Vue app set up using GraphQL we’ll need to do two things. First, we’ll install vue-apollo (a Vue plugin for the Apollo GraphQL client) as well as apollo-boost, which bootstraps the configuration of Apollo. With these you’ll be able to:

  • Manually run GraphQL queries and mutations from any Vue component via the this.$apollo helper
  • Automatically map GraphQL queries to a component’s data fields by adding the apollo property to your component

These queries will also lazy load data from Apollo’s cache to minimize requests across multiple components.

Second, we’ll add webpack configuration so that you can store your GraphQL queries and mutations in separate files (.gql or .graphql), and import them directly into your component files.

Let’s begin by installing the required npm packages:

npm install graphql vue-apollo apollo-boost graphql-tag

Setting up VueApollo

To set up the VueApollo plugin, we’ll use the ApolloClient helper from apollo-boost, and pass it the URL of your GraphQL API endpoint:

main.js

import Vue from 'vue';
import App from './App.vue';
import ApolloClient from 'apollo-boost';
import VueApollo from 'vue-apollo';

// Create the apolloProvider using the ApolloClient helper
// class from apollo-boost
const apolloProvider = new VueApollo({
  defaultClient: new ApolloClient({
    uri: '<YOUR_GRAPHQL_ENDPOINT_HERE>'
  })
});

// Add VueApollo plugin
Vue.use(VueApollo);

// Instantiate your Vue instance with apolloProvider
new Vue({
  apolloProvider,
  render: h => h(App),
}).$mount('#app')

With this configuration in place, you now have access to this.$apollo in all your components, and you can add smart queries to them using the apollo property.

GraphQL file imports

To enable GraphQL file imports, update vue.config.js to use the included GraphQL loader from graphql-tag to parse all files with a .graphql or .gql extension:

vue.config.js

module.exports = {
    chainWebpack: (config) => {
        // GraphQL Loader
        config.module
          .rule('graphql')
          .test(/\.(graphql|gql)$/)
          .use('graphql-tag/loader')
          .loader('graphql-tag/loader')
          .end();
      },
};

Once this configuration is in place, you can create a .gql or .graphql file, and import it directly into your javascript files:

import MY_QUERY from "./my-query.gql";

This imported query (named MY_QUERY in the example) is a DocumentNode object, and can be passed directly to Apollo.

As a side note: If you have an existing GraphQL server, it’s usually possible to export your schema into a .gql file that contains the queries and mutations your server uses. Not only does this save a lot of time, but it helps minimize inconsistencies between the queries on the frontend and what the backend actually does.

Loading data with Apollo queries

With Apollo, you can configure any Vue component to map GraphQL queries to fields in its data object. You can do this by adding an apollo option to your component. Each field on this object is an Apollo Smart Query, which will automatically run the query (lazily loading from the cache) and then map the query results to a field in the component’s data. The name of the mapped data field will be the same as the field name within the apollo object.

For example, let’s say we needed to make a component load a list of blog posts, given a user ID, and display the total number of posts for that user. To do this using Apollo, you’ll need to define a GraphQL query that accepts userId as a variable and queries for that user’s posts. Here’s how that query might look:

posts.gql

query ($userId: String!) {
    posts(userId: $userId) {
        id 
        content
    }
}

We can then define an apollo object on the component that loads the data from the query into our component’s data:

posts.vue

<template>
    <p>
        Total number of posts: {{posts.length}}
    </p>
</template>
<script>
import POSTS_BY_USER from "./posts.gql";

export default {
    name: 'NumPosts',
    props: ['userId'],
    data() {
        return {
            // This value is updated by apollo when the query
            // is run and receives data
            posts: [],
        }
    },
    // This smart query will automatically run the POSTS_BY_USER
    // query when the component is mounted. It also responds to 
    // changes in any of its variables, and will automatically 
    // rerun the query if the userId changes.
    apollo: {
        posts: {
            query: POSTS_BY_USER,
            variables() {
                return { userId: this.userId };
            },
        },
    },
}
</script>

The smart query accepts a GraphQL query and a variables object where the keys are the variable names and the values are the variable values. What this will do is run the POSTS_BY_USER query when the component mounts, and store the results of that query in the posts data field. Then, any time one of the variables changes (in this case, it would happen if the userId prop receives a new value), the query will be rerun and posts will again be updated. Additionally, the results of the query are stored in Apollo’s cache. So, if another component has the same smart query in it, only one actual request will be made.

Updating data with Apollo mutations

To update existing objects using GraphQL, we use mutations. GraphQL mutations look similar to queries, except that on the server, they will update or create new resources. For example, a mutation to update an existing user’s post would look like this:

mutation ($id: Int!, $content: String!) {
    updatePost(id: $id, content: $content) {
        id
        content
    }
}

Running this mutation will cause the server to update the post with the specified $id. To run GraphQL mutations from your component, you can use the Apollo mutate method:

this.$apollo.mutate({
    mutation: UPDATE_POST,
    variables: { id: this.post?.id, content: this.newContent }
});

This function sends the UPDATE_POST mutation to the server to be run, and then updates the cache for all occurrences of the post with the given id when it receives the response.

For updating existing objects, Apollo is able to automatically handle updating the cache. However, when creating a new object, the cache needs to be updated manually. I’ll demonstrate this in the next section.

Creating data and handling cache updates

Apollo has a global cache of query results, which prevents duplicate requests from being made when the same query is run again in the future. In the cache, each query is indexed using the query itself, and the variables it was run with.

When you run a mutation that updates an existing object, Apollo is smart enough to update the cache because it can use the ID of that object (from the mutation’s variables) to find all cached queries that include it. However, when creating new objects, Apollo won’t update the cache because there’s no object in any cached queries with the ID of the new object. This is why you’ll have to either update the cache yourself, or specify which queries need to be re-fetched after running the mutation.

While specifying the queries to re-fetch makes the code much simpler, it might make more sense to do a manual update if the query to be re-fetched is costly.

Continuing with our blog posts example, let’s assume we have a query POSTS_BY_USER, which returns a list of all posts for a given user ID. If we wanted to create a new post, we’d need to update the cached results for POSTS_BY_USER with the given user ID to include the new post.

To create a new post, and then re-fetch the POSTS_BY_USER query, it would look like this:

this.$apollo.mutate({
    mutation: ADD_POST,
    variables: { content: this.newPostContent },
    refetchQueries: [
        {
            query: POSTS_BY_USER, 
            variables: { userId: this.currentUser.id }
        }
    ]
});

To do the same exact thing with a manual cache update, it would look like this:

this.$apollo.mutate({
    mutation: ADD_POST,
    variables: { content: this.newPostContent },
    update: (cache, result) => {
        // The new post returned from the server. Notice how 
        // the field on data matches the name of the mutation 
        // in the GraphQL code.
        let newPost = result.data.addPost;

        // Queries are cached using the query itself, and the
        // variables list used.
        let cacheId = {
            query: POSTS_BY_USER,
            variables: { userId: this.currentUser.id },
        };

        // Get the old list from the cache, and create a new array
        // containing the new item returned from the server along 
        // with the existing items.
        const data = cache.readQuery(cacheId);
        const newData = [...data.postsByUser, newPost];

        // Write the new array of data for this query into 
        // the cache.
        cache.writeQuery({
            ...cacheId,
            data: { postsByUser: newData },
        });
    },
    // By specifying optimistic response, we're instructing apollo 
    // to update the cache before receiving a response from the 
    // server. This means the UI will be updated much quicker.
    optimisticResponse: {
        __typename: "Mutation",
        addPost: {
            __typename: "Post",
            id: "xyz-?",
            content: this.newPostContent,
            userId: this.currentUser.id,
        },
    },
});

There’s a few things to note about the above code. First, it specifies an optimisticResponse field on the mutation. This field can be used to pass a response to Apollo before the server actually responds. If you know exactly what the response will look like, you can use it to enhance the user experience by making the UI respond right away instead of waiting while the server processes the request.

As you can see, manually updating the cache requires quite a bit of code to accomplish, and is a bit hard to read. In my own projects, I found it best to abstract the Apollo mutations into separate helper functions that just accept the variables object. This way, the cache updates stay separate from the business logic of the components, and aren’t scattered throughout the codebase.

Conclusion

And that’s it! My experience converting an existing Vue codebase to use Apollo/​GraphQL was a very positive one. The resulting code had much better performance than manually sending requests and updating a Vuex store, and was a lot easier to work on.

Have any questions? Feel free to leave a comment!


javascript graphql vue
Previous page • Page 2 of 198 • Next page

Popular Tags


Archive


Search our blog