MotoPress Acquires Gutenix WordPress Theme

MotoPress, a theme and plugin shop in operation since 2013, has acquired the Gutenix WordPress theme and its commercial ZeGuten blocks plugin for Gutenberg. The free theme currently has more than 700 active installs after nine months on WordPress.org.

MotoPress already has a number of successful niche WordPress themes and plugins but Gutenix fills the gap for a multipurpose theme. It was developed to work well with popular page builder plugins, and includes dedicated starter template libraries for Elementor, Brizy, and the block editor. The theme’s commercial upgrades bundle the GutenixPro premium plugin, 30+ starter sites, and the ZeGuten plugin.

MotoPress is more well-known for its Hotel Booking plugin and its associated add-ons. The company also develops a block collection plugin called Getwid Gutenberg blocks, which has more than 10,000 active installs and is growing in popularity. Getwid is unique in that the collection is aimed at developers. The plugin comes with a free style kit that includes theme support snippets and CSS classes to accelerate the development process of building custom themes. Its accompanying Getwid Base Theme has more than 2,000 active installs.

Even though MotoPress is already developing its own block collection and base theme, the company saw value in acquiring a more multipurpose theme aimed at users of popular page builders.

”Such a multipurpose theme is something we always wanted to create – but have never had the time resource to invest in such a multidimensional and complex thing,” MotoPress CEO Alexander Matienko said.

“After a fruitful exchange of experiences and visions with the Gutenix creators,I realized one thing. Not only are our companies aligned in our Gutenberg-driven passion, but we both have realistic views on the current WordPress market demands, where Elementor and other builders have been great value for people.”

Gutenix is MotoPress’ first acquisition and the company plans to keep it as a separate product that is independent of MotoPress Club membership.

Model Experiments, Tracking, and Registration Using MLflow on Databricks and StreamSets

Learn how StreamSets, a modern data integration platform for DataOps, can help expedite operations at some of the most crucial stages of machine learning lifecycle and MLOps.

Data Acquisition and Preparation

Machine learning models are only as good as the quality of data and the size of datasets used to train the models. Data has shown that data scientists spend around 80% of their time on preparing and managing data for analysis and 57% of the data scientists regard cleaning and organizing data as the least enjoyable part of their work. This further validates the idea of  MLOps and the need for collaboration between data scientists and data engineers.

How to Extract Data From Tables in Multiple Google Docs and Combine Into One Table in Coda

If your organization creates multiple Google Docs every day and you want a better way to sort, filter, and organize all these Google Docs, this solution may be useful for you. This tutorial walks you through how to extract the important metadata from a table in a Google Doc and sync that data into a table in Coda.

I often see templates for project briefs, meeting notes, or candidate interview as Google Docs at other organizations which are duplicated over and over again. These Google Docs are then stored in Google Drive which can get very unwieldy to manage unless someone is consistently organizing the folders in Google Drive. Another common trait in these Google Docs: a table near the top of the Google Doc summarizing what the doc is about.

How Graph Analytics Can Transform Your Business

Introduction

Your business is operating in an ever more connected world where the understanding of complex relationships and interdependencies between different data points is crucial to many decision-making processes. This is the main reason why graph databases have gained a lot of interest in the past few years and have become that fastest-growing database category. They offer powerful data modeling and analysis capabilities your business can use to easily model real-world complex systems and answer challenging questions previously hard to address.

What Is a Graph Database?

You might not be aware of it, but many of the services you use on a daily basis are powered by a graph database. Such examples include Google’s search engine, Linkedin’s connection recommendations, UberEats food recommendations and Gmail’s autocomplete feature. Simply put, a graph database is a data management system specifically engineered and optimized to store and analyze complex networks of connected data where relationships are equally important to individual data points. As a result, they offer a highly efficient, flexible, and overall elegant way to discover connections and patterns within your data that are otherwise very hard to see.

How Healthcare Sectors Can Make Use of the CIoMT to Fight Against Covid-19

The unprecedented outbreak of the 2019 novel coronavirus, termed as COVID-19 by the World Health Organization (WHO), has placed numerous governments around the world in a precarious situation.

The scarcity of resources to endure the COVID-19 outbreak combined with the fear of overburdened healthcare systems has forced a majority of these countries into a state of partial or complete lockdown. The number of laboratory-confirmed COVID-19 cases has been increasing at an alarming rate throughout the world, with a report from WHO stating that there are more than 3.23 million confirmed cases as of August 2020. Adding to these woes, numerous false reports, misinformation, and unsolicited fears in regards to coronavirus, are being circulated regularly since the outbreak of COVID19.

Deeper DX

Shawn Wang thinks there are deeper, perhaps more uncomfortable, places to go with developer experience (DX) beyond the surface-level stuff that we recently covered. Sure, sure, documentation, CLIs, good demos. But there are much harder questions to answer that are part of the real DX. Shawn lists eight really good ones. I’ll share this one:

No product launches feature complete. Nobody expects you to. The true test is whether you address it up front or hide it like a dirty secret. As developers explore your offering, they will find things they want, that you don’t have, and will tell you about it. How long do you make developers dig to find known holes in your product? Do developers have confidence you will ship or reject these features promptly, or are they for a “v2” that will never come?

Direct Link to ArticlePermalink


The post Deeper DX appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

API Security Weekly: Issue #98

This week, we take a look at the recently reported API vulnerabilities in the COVID-19 tracing app Aura and in Kubernetes, some API security best practices, and a talk on OWASP API Top 10 from DEF CON 2020.

Vulnerability: Aura COVID-19 Tracing App

Another mandatory COVID-19 tracing app, was found to leak personal information and health status of users. This time it was Aura, an app that Albion College in Michigan has made mandatory for all students.

Elementor 3.0 Allows Users to Create a Personalized Design System

Elementor version 3.0 was launched on Tuesday. This release is the first major update to the plugin in over two years and is one of the largest upgrades in its history. The new version focuses on a design system, a new theme builder, and performance improvements. The driving motivation behind this release was to create global design tools, which is a shift from the plugin’s roots as a mere page builder.

One of my biggest complaints about builder plugins is that they have often approached design on the individual page level first. However, web design is not about how you can fancy up a page. It is about taking a holistic approach to the overall design of the site. When building single pages, users of such plugins far too often create more work for themselves, much of it better handled on a global scale. One of the cornerstones of development is to not repeat work you have already done. Builder plugins can too easily push those who use them toward such bad habits.

Design should handle the foundational, global features first. Then, drill down to the atomic level when necessary. Builder plugins have almost exclusively gotten this backward in the past.

Elementor 3.0 seeks to solve this problem by introducing its design system and a new theme builder. The latter is part of its pro offering. The design system is essentially a global style creator and is available in both the free and pro versions. This is a welcome addition to the plugin and should create a solution for those foundational elements that the plugin has been missing.

“Creating a site with a design system in mind (i.e. style guide, colors, and typography) is how professionals approach building websites,” said Ariel Klikstein, the co-founder and CTO of Elementor. “For many creators, this is an integral part of building the site as it helps them, their teams, and their clients to align and communicate around a consistent vision.”

The Elementor team is coming to terms with the principles that have long guided web designers. The goal is to apply these principles to a user interface, breaking outside the confines of code.

“Design system capabilities are among the pillars of building professional websites, as they give the ability to view and control the site elements from a centralized hub and apply sitewide changes to overall colors, typography, and layout,” said Klikstein.

Elementor’s Design System

Elementor global colors from design feature launched in 3.0.
Editing global colors with Elementor’s design system.

Elementor is pitching its new design system as revolutionary. However, such design systems have long existed in the WordPress ecosystem. Theme developers have created similar systems for well over a decade, and they have since capitalized on WordPress’s built-in customizer to do it in real time.

The question is whether this new system ups the ante, creating a new baseline in which others must compete.

That will be for users to decide. However, it does offer a plethora of options under its Site Settings menu. It allows end-users to customize colors, typography, and several other elements across the site. Current plugin users will have tools in their hands to do some more amazing things with Elementor, and they will be able to do them in a much more streamlined manner. Ultimately, it should save time and make it possible to update the site over the long term without re-editing old work.

It is not particularly revolutionary, but it is something that should be standard for any sort of visual design system.

“While it’s true that applying global styles was always possible using custom CSS code and themes, in Elementor V3.0 we made these options truly global,” said Klikstein. “Today they are independent of a theme, plugin, or widget as part of the element-based web design paradigm. The design system features are integrated into the editor workflow, without the need to use a single line of code. This will let the user implement global colors and fonts across any site element — be it a button, heading, or background. Then, if the user decides to change the color or a font style, he or she can change it once and apply it wherever it was previously placed in the global setting.”

To not mislead readers, note that most themes that have implemented such systems have also not required custom CSS or other code.

Perhaps the bigger question is whether this new design system will be better than the upcoming global styles feature in Gutenberg and core WordPress. The aims of the two are similar, but WordPress will undoubtedly launch its feature with a much more limited set of options. WordPress will also need buy-in from theme authors.

Klikstein did not directly respond to the question of how WordPress’s global styles feature impacted any decision that went into Elementor’s design system feature. However, when cutting through the marketing cruft, he did say, “It’s great to see that Gutenberg/WordPress is also moving in this direction because we believe this is the best way to create consistent and maintainable websites.” He also said this feature was on the roadmap since the plugin’s earlier theme builder concept.

Gutenberg may not be much of a consideration for Elementor’s development team. They are clearly carving their own path to success and outpacing others in the race to building websites through a visual interface.

Multi-Cluster Vulnerability Scanning with Alcide

Introduction

Kubernetes provides the freedom to rapidly build and ship applications while dramatically minimizing deployment and service update cycles. 

However, the velocity of application deployment requires a new approach that involves integrating tools as early as possible in the deployment pipeline and inspecting the code and configuration against Kubernetes security best practices.

Top 5 Big Data Certifications to Help You Break Into the Industry

Before we go ahead and delve deeper into the different types of big data certification programs, it is important to know why there is so much hype about the variety you can opt for. It is important to know why there is so much hype about big data training programs. The prime reason for this is the great impact and use of data in recent times. Around 90 % of all the data has been created in the last two years. Irrespective of the type of industry, data seems to be having an impact on it. Everything works on data with all the latest technologies like Artificial Intelligence, Machine Learning, IoT, or Data Analysis. Thus, there is a great demand for professionals who can assess the data and draw inferences from the same.

If you also wish to make a career in the field of big data, in that case, you must know about the right certification program that, and most importantly choosing the right platform becomes important. This will not only give you the theoretical knowledge but will also give you an understanding of the practical implications of the same. In this blog, we help you explore the best five big data certification and big data training programs to take your career graph to a new height.

Going Jamstack with React, Serverless, and Airtable

The best way to learn is to build. Let’s learn about this hot new buzzword, Jamstack, by building a site with React, Netlify (Serverless) Functions, and Airtable. One of the ingredients of Jamstack is static hosting, but that doesn’t mean everything on the site has to be static. In fact, we’re going to build an app with full-on CRUD capability, just like a tutorial for any web technology with more traditional server-side access might.

Why these technologies, you ask?

You might already know this, but the “JAM” in Jamstack stands for JavaScript, APIs, and Markup. These technologies individually are not new, so the Jamstack is really just a new and creative way to combine them. You can read more about it over at the Jamstack site.

One of the most important benefits of Jamstack is ease of deployment and hosting, which heavily influence the technologies we are using. By incorporating Netlify Functions (for backend CRUD operations with Airtable), we will be able to deploy our full-stack application to Netlify. The simplicity of this process is the beauty of the Jamstack.

As far as the database, I chose Airtable because I wanted something that was easy to get started with. I also didn’t want to get bogged down in technical database details, so Airtable fits perfectly. Here’s a few of the benefits of Airtable:

  1. You don’t have to deploy or host a database yourself
  2. It comes with an Excel-like GUI for viewing and editing data
  3. There’s a nice JavaScript SDK

What we’re building

For context going forward, we are going to build an app where you can use to track online courses that you want to take. Personally, I take lots of online courses, and sometimes it’s hard to keep up with the ones in my backlog. This app will let track those courses, similar to a Netflix queue.

 

One of the reasons I take lots of online courses is because I make courses. In fact, I have a new one available where you can learn how to build secure and production-ready Jamstack applications using React and Netlify (Serverless) Functions. We’ll cover authentication, data storage in Airtable, Styled Components, Continuous Integration with Netlify, and more! Check it out  →

Airtable setup

Let me start by clarifying that Airtable calls their databases “bases.” So, to get started with Airtable, we’ll need to do a couple of things.

  1. Sign up for a free account
  2. Create a new “base”
  3. Define a new table for storing courses

Next, let’s create a new database. We’ll log into Airtable, click on “Add a Base” and choose the “Start From Scratch” option. I named my new base “JAMstack Demos” so that I can use it for different projects in the future.

Next, let’s click on the base to open it.

You’ll notice that this looks very similar to an Excel or Google Sheets document. This is really nice for being able tower with data right inside of the dashboard. There are few columns already created, but we add our own. Here are the columns we need and their types:

  1. name (single line text)
  2. link (single line text)
  3. tags (multiple select)
  4. purchased (checkbox)

We should add a few tags to the tags column while we’re at it. I added “node,” “react,” “jamstack,” and “javascript” as a start. Feel free to add any tags that make sense for the types of classes you might be interested in.

I also added a few rows of data in the name column based on my favorite online courses:

  1. Build 20 React Apps
  2. Advanced React Security Patterns
  3. React and Serverless

The last thing to do is rename the table itself. It’s called “Table 1” by default. I renamed it to “courses” instead.

Locating Airtable credentials

Before we get into writing code, there are a couple of pieces of information we need to get from Airtable. The first is your API Key. The easiest way to get this is to go your account page and look in the “Overview” section.

Next, we need the ID of the base we just created. I would recommend heading to the Airtable API page because you’ll see a list of your bases. Click on the base you just created, and you should see the base ID listed. The documentation for the Airtable API is really handy and has more detailed instructions for find the ID of a base.

Lastly, we need the table’s name. Again, I named mine “courses” but use whatever you named yours if it’s different.

Project setup

To help speed things along, I’ve created a starter project for us in the main repository. You’ll need to do a few things to follow along from here:

  1. Fork the repository by clicking the fork button
  2. Clone the new repository locally
  3. Check out the starter branch with git checkout starter

There are lots of files already there. The majority of the files come from a standard create-react-app application with a few exceptions. There is also a functions directory which will host all of our serverless functions. Lastly, there’s a netlify.toml configuration file that tells Netlify where our serverless functions live. Also in this config is a redirect that simplifies the path we use to call our functions. More on this soon.

The last piece of the setup is to incorporate environment variables that we can use in our serverless functions. To do this install the dotenv package.

npm install dotenv

Then, create a .env file in the root of the repository with the following. Make sure to use your own API key, base ID, and table name that you found earlier.

AIRTABLE_API_KEY=<YOUR_API_KEY>
AIRTABLE_BASE_ID=<YOUR_BASE_ID>
AIRTABLE_TABLE_NAME=<YOUR_TABLE_NAME>

Now let’s write some code!

Setting up serverless functions

To create serverless functions with Netlify, we need to create a JavaScript file inside of our /functions directory. There are already some files included in this starter directory. Let’s look in the courses.js file first.

const  formattedReturn  =  require('./formattedReturn');
const  getCourses  =  require('./getCourses');
const  createCourse  =  require('./createCourse');
const  deleteCourse  =  require('./deleteCourse');
const  updateCourse  =  require('./updateCourse');
exports.handler  =  async  (event)  =>  {
  return  formattedReturn(200, 'Hello World');
};

The core part of a serverless function is the exports.handler function. This is where we handle the incoming request and respond to it. In this case, we are accepting an event parameter which we will use in just a moment.

We are returning a call inside the handler to the formattedReturn function, which makes it a bit simpler to return a status and body data. Here’s what that function looks like for reference.

module.exports  =  (statusCode, body)  =>  {
  return  {
    statusCode,
    body: JSON.stringify(body),
  };
};

Notice also that we are importing several helper functions to handle the interaction with Airtable. We can decide which one of these to call based on the HTTP method of the incoming request.

  • HTTP GET → getCourses
  • HTTP POST → createCourse
  • HTTP PUT → updateCourse
  • HTTP DELETE → deleteCourse

Let’s update this function to call the appropriate helper function based on the HTTP method in the event parameter. If the request doesn’t match one of the methods we are expecting, we can return a 405 status code (method not allowed).

exports.handler = async (event) => {
  if (event.httpMethod === 'GET') {
    return await getCourses(event);
  } else if (event.httpMethod === 'POST') {
    return await createCourse(event);
  } else if (event.httpMethod === 'PUT') {
    return await updateCourse(event);
  } else if (event.httpMethod === 'DELETE') {
    return await deleteCourse(event);
  } else {
    return formattedReturn(405, {});
  }
};

Updating the Airtable configuration file

Since we are going to be interacting with Airtable in each of the different helper files, let’s configure it once and reuse it. Open the airtable.js file.

In this file, we want to get a reference to the courses table we created earlier. To do that, we create a reference to our Airtable base using the API key and the base ID. Then, we use the base to get a reference to the table and export it.

require('dotenv').config();
var Airtable = require('airtable');
var base = new Airtable({ apiKey: process.env.AIRTABLE_API_KEY }).base(
  process.env.AIRTABLE_BASE_ID
);
const table = base(process.env.AIRTABLE_TABLE_NAME);
module.exports = { table };

Getting courses

With the Airtable config in place, we can now open up the getCourses.js file and retrieve courses from our table by calling table.select().firstPage(). The Airtable API uses pagination so, in this case, we are specifying that we want the first page of records (which is 20 records by default).

const courses = await table.select().firstPage();
return formattedReturn(200, courses);

Just like with any async/await call, we need to handle errors. Let’s surround this snippet with a try/catch.

try {
  const courses = await table.select().firstPage();
  return formattedReturn(200, courses);
} catch (err) {
  console.error(err);
  return formattedReturn(500, {});
}

Airtable returns back a lot of extra information in its records. I prefer to simplify these records with only the record ID and the values for each of the table columns we created above. These values are found in the fields property. To do this, I used the an Array map to format the data the way I want.

const { table } = require('./airtable');
const formattedReturn = require('./formattedReturn');
module.exports = async (event) => {
  try {
    const courses = await table.select().firstPage();
    const formattedCourses = courses.map((course) => ({
      id: course.id,
      ...course.fields,
    }));
    return formattedReturn(200, formattedCourses);
  } catch (err) {
    console.error(err);
    return formattedReturn(500, {});
  }
};

How do we test this out? Well, the netlify-cli provides us a netlify dev command to run our serverless functions (and our front-end) locally. First, install the CLI:

npm install -g netlify-cli

Then, run the netlify dev command inside of the directory.

This beautiful command does a few things for us:

  • Runs the serverless functions
  • Runs a web server for your site
  • Creates a proxy for front end and serverless functions to talk to each other on Port 8888.

Let’s open up the following URL to see if this works:

We are able to use /api/* for our API because of the redirect configuration in the netlify.toml file.

If successful, we should see our data displayed in the browser.

Creating courses

Let’s add the functionality to create a course by opening up the createCourse.js file. We need to grab the properties from the incoming POST body and use them to create a new record by calling table.create().

The incoming event.body comes in a regular string which means we need to parse it to get a JavaScript object.

const fields = JSON.parse(event.body);

Then, we use those fields to create a new course. Notice that the create() function accepts an array which allows us to create multiple records at once.

const createdCourse = await table.create([{ fields }]);

Then, we can return the createdCourse:

return formattedReturn(200, createdCourse);

And, of course, we should wrap things with a try/catch:

const { table } = require('./airtable');
const formattedReturn = require('./formattedReturn');
module.exports = async (event) => {
  const fields = JSON.parse(event.body);
  try {
    const createdCourse = await table.create([{ fields }]);
    return formattedReturn(200, createdCourse);
  } catch (err) {
    console.error(err);
    return formattedReturn(500, {});
  }
};

Since we can’t perform a POST, PUT, or DELETE directly in the browser web address (like we did for the GET), we need to use a separate tool for testing our endpoints from now on. I prefer Postman, but I’ve heard good things about Insomnia as well.

Inside of Postman, I need the following configuration.

  • url: localhost:8888/api/courses
  • method: POST
  • body: JSON object with name, link, and tags

After running the request, we should see the new course record is returned.

We can also check the Airtable GUI to see the new record.

Tip: Copy and paste the ID from the new record to use in the next two functions.

Updating courses

Now, let’s turn to updating an existing course. From the incoming request body, we need the id of the record as well as the other field values.

We can specifically grab the id value using object destructuring, like so:

const {id} = JSON.parse(event.body);

Then, we can use the spread operator to grab the rest of the values and assign it to a variable called fields:

const {id, ...fields} = JSON.parse(event.body);

From there, we call the update() function which takes an array of objects (each with an id and fields property) to be updated:

const updatedCourse = await table.update([{id, fields}]);

Here’s the full file with all that together:

const { table } = require('./airtable');
const formattedReturn = require('./formattedReturn');
module.exports = async (event) => {
  const { id, ...fields } = JSON.parse(event.body);
  try {
    const updatedCourse = await table.update([{ id, fields }]);
    return formattedReturn(200, updatedCourse);
  } catch (err) {
    console.error(err);
    return formattedReturn(500, {});
  }
};

To test this out, we’ll turn back to Postman for the PUT request:

  • url: localhost:8888/api/courses
  • method: PUT
  • body: JSON object with id (the id from the course we just created) and the fields we want to update (name, link, and tags)

I decided to append “Updated!!!” to the name of a course once it’s been updated.

We can also see the change in the Airtable GUI.

Deleting courses

Lastly, we need to add delete functionality. Open the deleteCourse.js file. We will need to get the id from the request body and use it to call the destroy() function.

const { id } = JSON.parse(event.body);
const deletedCourse = await table.destroy(id);

The final file looks like this:

const { table } = require('./airtable');
const formattedReturn = require('./formattedReturn');
module.exports = async (event) => {
  const { id } = JSON.parse(event.body);
  try {
    const deletedCourse = await table.destroy(id);
    return formattedReturn(200, deletedCourse);
  } catch (err) {
    console.error(err);
    return formattedReturn(500, {});
  }
};

Here’s the configuration for the Delete request in Postman.

  • url: localhost:8888/api/courses
  • method: PUT
  • body: JSON object with an id (the same id from the course we just updated)

And, of course, we can double-check that the record was removed by looking at the Airtable GUI.

Displaying a list of courses in React

Whew, we have built our entire back end! Now, let’s move on to the front end. The majority of the code is already written. We just need to write the parts that interact with our serverless functions. Let’s start by displaying a list of courses.

Open the App.js file and find the loadCourses function. Inside, we need to make a call to our serverless function to retrieve the list of courses. For this app, we are going to make an HTTP request using fetch, which is built right in.

Thanks to the netlify dev command, we can make our request using a relative path to the endpoint. The beautiful thing is that this means we don’t need to make any changes after deploying our application!

const res = await fetch('/api/courses');
const courses = await res.json();

Then, store the list of courses in the courses state variable.

setCourses(courses)

Put it all together and wrap it with a try/catch:

const loadCourses = async () => {
  try {
    const res = await fetch('/api/courses');
    const courses = await res.json();
    setCourses(courses);
  } catch (error) {
    console.error(error);
  }
};

Open up localhost:8888 in the browser and we should our list of courses.

Adding courses in React

Now that we have the ability to view our courses, we need the functionality to create new courses. Open up the CourseForm.js file and look for the submitCourse function. Here, we’ll need to make a POST request to the API and send the inputs from the form in the body.

The JavaScript Fetch API makes GET requests by default, so to send a POST, we need to pass a configuration object with the request. This options object will have these two properties.

  1. method → POST
  2. body → a stringified version of the input data
await fetch('/api/courses', {
  method: 'POST',
  body: JSON.stringify({
    name,
    link,
    tags,
  }),
});

Then, surround the call with try/catch and the entire function looks like this:

const submitCourse = async (e) => {
  e.preventDefault();
  try {
    await fetch('/api/courses', {
      method: 'POST',
      body: JSON.stringify({
        name,
        link,
        tags,
      }),
    });
    resetForm();
    courseAdded();
  } catch (err) {
    console.error(err);
  }
};

Test this out in the browser. Fill in the form and submit it.

After submitting the form, the form should be reset, and the list of courses should update with the newly added course.

Updating purchased courses in React

The list of courses is split into two different sections: one with courses that have been purchased and one with courses that haven’t been purchased. We can add the functionality to mark a course “purchased” so it appears in the right section. To do this, we’ll send a PUT request to the API.

Open the Course.js file and look for the markCoursePurchased function. In here, we’ll make the PUT request and include both the id of the course as well as the properties of the course with the purchased property set to true. We can do this by passing in all of the properties of the course with the spread operator and then overriding the purchased property to be true.

const markCoursePurchased = async () => {
  try {
    await fetch('/api/courses', {
      method: 'PUT',
      body: JSON.stringify({ ...course, purchased: true }),
    });
    refreshCourses();
  } catch (err) {
    console.error(err);
  }
};

To test this out, click the button to mark one of the courses as purchased and the list of courses should update to display the course in the purchased section.

Deleting courses in React

And, following with our CRUD model, we will add the ability to delete courses. To do this, locate the deleteCourse function in the Course.js file we just edited. We will need to make a DELETE request to the API and pass along the id of the course we want to delete.

const deleteCourse = async () => {
  try {
    await fetch('/api/courses', {
      method: 'DELETE',
      body: JSON.stringify({ id: course.id }),
    });
    refreshCourses();
  } catch (err) {
    console.error(err);
  }
};

To test this out, click the “Delete” button next to the course and the course should disappear from the list. We can also verify it is gone completely by checking the Airtable dashboard.

Deploying to Netlify

Now, that we have all of the CRUD functionality we need on the front and back end, it’s time to deploy this thing to Netlify. Hopefully, you’re as excited as I am about now easy this is. Just make sure everything is pushed up to GitHub before we move into deployment.

If you don’t have a Netlify, account, you’ll need to create one (like Airtable, it’s free). Then, in the dashboard, click the “New site from Git” option. Select GitHub, authenticate it, then select the project repo.

Next, we need to tell Netlify which branch to deploy from. We have two options here.

  1. Use the starter branch that we’ve been working in
  2. Choose the master branch with the final version of the code

For now, I would choose the starter branch to ensure that the code works. Then, we need to choose a command that builds the app and the publish directory that serves it.

  1. Build command: npm run build
  2. Publish directory: build

Netlify recently shipped an update that treats React warnings as errors during the build proces. which may cause the build to fail. I have updated the build command to CI = npm run build to account for this.

Lastly, click on the “Show Advanced” button, and add the environment variables. These should be exactly as they were in the local .env that we created.

The site should automatically start building.

We can click on the “Deploys” tab in Netlify tab and track the build progress, although it does go pretty fast. When it is complete, our shiny new app is deployed for the world can see!

Welcome to the Jamstack!

The Jamstack is a fun new place to be. I love it because it makes building and hosting fully-functional, full-stack applications like this pretty trivial. I love that Jamstack makes us mighty, all-powerful front-end developers!

I hope you see the same power and ease with the combination of technology we used here. Again, Jamstack doesn’t require that we use Airtable, React or Netlify, but we can, and they’re all freely available and easy to set up. Check out Chris’ serverless site for a whole slew of other services, resources, and ideas for working in the Jamstack. And feel free to drop questions and feedback in the comments here!


The post Going Jamstack with React, Serverless, and Airtable appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Design.dev Review: A New Place to Find Free High-Quality Design Resources

Whether you are a graphic designer, web designer or developer, working in the UI or UX field, or pretty much anything related to digital and print production, you likely have utilized premade digital assets in your projects. There are a variety of websites that offer these resources, but today we’d like to introduce you to the “new kid on the block”: Design.dev.

Design.dev was launched only a few months ago with the goal of providing high-quality free and premium digital resources for creative people, to help speed up your workflow and save you time and money in the process. Unlike other similar websites, the resources here are currently exclusive to Design.dev, so you won’t find them anywhere else. While this could change in the future as the site grows, for now this makes the website a great place to find unique creations to use in your projects.

Let’s take a closer look at what Design.dev has to offer, how it works, and why we think this resource is worth visiting.

First Impression: Easy To Search, Filter, and Find

Upon first arriving on the home page, you will see a grid of 12 product offerings below a category filter. Click on any of the categories (or multiple categories) to filter down to what you are searching for. Current categories include Icons, Illustrations, Premium, Print, Social, UI Kits, and Website Templates. There is a secondary filter that narrows your results down even more to the type of file included in the download. These filters include Illustrator, Affinity Designer, Photoshop, Sketch, and Figma. So whatever design software you are most comfortable with, you can filter to make sure you’re getting the editable file type you are looking for. 

You can also search for specific keywords using the search feature near the top of the page. 

Products are clearly labeled with a green “Free” banner or a blue “Premium” banner, so you know right away what the availability of each product is based on your membership in one of the two tiers. Each product listing also includes icons denoting the design software file type(s) it is available in, along with the category to which it belongs.

All of this will save you time when you are looking for something specific.

Helpful Asset Details

Click on a product to learn more about it and you will find a brief description, followed by a carousel of sample images. Click on any of the images in the carousel to view it full size, which is helpful to see the detail within each offering.

There is also a sidebar on each single product page that tells you the category, file format(s), number of elements in the file and the file download size. Good to know what you’re getting into before you download the file.

Single, Simple License: Use In Personal and Commercial Projects Without Attribution

You don’t have to worry about any complex legal jargon or uncertainty of what you can or can’t do with the items you download. Every product on Design.dev falls under the same license and can be used in both personal and commercial projects without attribution. You can modify them however you want as well. The only limitation is you that cannot resell them.

Some Example Digital Resources We Liked

10 Abstract Background Illustrations (Free)

Who doesn’t use backgrounds in their projects? These ten unique background illustrations can be used in a variety of projects and they are truly one of a kind.

Restaurant Website Template (Premium)

This well-designed and complete website template kit includes 5 pages in both desktop and mobile versions, so you can use it for your next restaurant website and simply update the branding, colors and content to match you or your client’s needs.

36 Symbols of Summer (Free)

These playful illustrations can be used as icons or however else you’d like to add fun and individuality to your summer-themed project.

Furr – Mobile Ecommerce UI Kit (Free)

This clean, well-designed and thought out mobile ecommerce kit includes 12 app screens that take the user from signup through shopping to purchase. You could use this kit in a multitude of contexts by simply changing out the products and editing the branding for a quick mockup to present to your client.

Free Membership: Simple to Sign Up and Start Downloading Assets

Price is always a major consideration when choosing where to get your digital assets to use in your projects. That’s one of the primary reasons Design.dev stands out in its field. With a significant percentage of their offerings available for free, and new free products being added regularly, the website should become a regular part of your resource-searching routine. Best of all, the requirements for membership are simple: just your name, email address, username, and password is all that’s needed to start downloading every single free product on the website!

Premium Membership For Only $10 per Month

If you would like to up your game and increase the span of products you can download, you can sign up for a Premium membership for only $10 per month. That’s a great price, and it is for a limited time for “early adopters”. This means that at some point in time that price is going to increase, but you can lock in the $10 monthly subscription now and even when the price goes up for new members, yours will not change. It’s a great way to lock in the low price now so that in the future you will still have access to all of the Premium products they will be adding without having to pay anything additional.

Final Thoughts

It is obvious that this new website has the potential to become a go-to resource for designers and developers alike. While the current product offering is relatively smaller than other, more established websites, Design.dev looks to be committed to continually growing, improving, and adding many more products on a regular basis. That, paired with the unique and exclusive design resources currently listed, make this website one to bookmark and watch. We encourage you to give it a visit and see what you can find that will help you save time and money in your future projects, as well as possibly spark some inspiration and imagination for your own designs.

The post Design.dev Review: A New Place to Find Free High-Quality Design Resources appeared first on Codrops.

Experimental Triangle Image Transitions with WebGL

Do you love triangles? I do. And because its boring to like all triangles, I specifically target my love to equilateral ones, like this one:

equilateral triangle
Isn’t this beautiful? ?

Why

Nobody: …
Nobody at all: …
Me: lets make full screen image transitions with equilateral triangles!

And although that pretty much sums up the reasoning part, I also did this for the love. For the love of equilateral triangles.

So let’s get started! Just as I did in my previous animations, I will need some plane geometry in front of a viewer.

But if I use the three.js PlaneBufferGeometry,

Not epic. Boring triangles.

…those triangles are not what we are looking for. To create equilateral ones, i just created my geometry with math! The final result looks like this:

Woah, now this is pure beauty. Don’t judge me.

What’s the math behind that? Pretty easy actually: with equilateral triangles you know exactly all the coordinates and sizes:

equilateral triangle math
Math.

Knowing those sizes, I can easily calculate as many triangles as I need. Also, I can’t help sharing this amazing resource on all kinds of hexagonal and equilateral triangle grids. That’s an amazing read regardless of your geometric preferences.

Anyhow, I got this kind of grid:

equilateral triangle strip
I scaled this to fit the whole screen.

Animation the triangles

Now that we have a grid, we can use GLSL and a vertex shader to animate those triangles. I recommend you read more about shaders and GLSL in “The Book Of Shaders“.

The good news is that we can animate each triangle separately; we can even animate each of its vertices on their own!

An example animation.

In code that looks like this:

vec3 newPosition = move(position, progress);

Where the move function moves and rotates the default position with the change of the progress value. That could be a simple shift on the X-axis, for example:

vec3 newPosition = position + progress*vec3(1.,0.,0.);

Or anything you could imagine doing with numbers.

I had a lot of fun experimenting with those effects, hope you will like them. And the possibilities here are endless of course.

Tell me, or better show me, what geometry figures do you like to animate? 🙂

P.S.: I do love all kinds of triangles, I hope no triangle will get offended or mad after reading this article.

The post Experimental Triangle Image Transitions with WebGL appeared first on Codrops.