However, in Windows it failed due to rm having a different syntax and Powershell not being able to execute the nodemon exec command as tsc was not installed globally.
The solution was replacing rm with node rimraf (install with npm i rimraf --save-dev) and the single quotes with escaped double ones:
I decided to take the IBM Cloud Solution Advisor certification to consolidate my existing knowledge and prove my skills to my customers. Next are the steps I took to achieve it.
Taking the online courses
I signed in to the certification learning path page with my IBM account. If you don’t have one you can easily register with your email for free.
The learning path is structured in several courses, each represented by a card and hosted in Cognitive Class. You can authenticate with your IBM account so you don’t need to register again.
IBM Certified Solution Advisor – IBM Cloud Foundations V2 certification path
Each course is composed of several modules, which start with a description of its objectives. Then there are several videos made by skilled IBM engineers. The explanations are very clear and they also have subtitles and transcripts so they are very easy to follow even for beginners.
An IBM engineer explaining the differences between RedHat OpenShift and Kubernetes
There are technical demos and hands-on labs too so you can practice with some of the course technologies.
I liked that this was not a strictly technical certification and there were subjects like the IBM Garage Method related to applying technology to corporate processes.
Finally, there is an outline of the module, a practice, and a partial exam. At the end of each module, there is a final exam. If you get a passing score you will get a certificate and a badge you can collect on Creedly. Even if you don’t pass these, they will help you to know which parts of the course you need to review for the certification exam.
Once you complete all courses you will be ready to take the certification exam.
Registering for the online exam: no Linux support
Tux wants to become certified too.
You can register for the certification exam by clicking on the Purchase Certification Exam button on the Learning Path page. You will be redirected to the Pearson VUE page, where you need to register with your email.
You can choose between taking the exam online or from your home or office. I selected the latter but when checking the technical requirements I noticed that they only support Windows and macOS.
As all my computers run Linux, this was not an option for me. It would be nice to support it as many developers and system administrators use it.
Registering for the onsite exam
Fortunately, there were several Pearson VUE centers in my city, so I registered onsite. The process is very straightforward and you start choosing from a list of centers from a map and an ordered by distance list from your location.
A map showing the available tests centers
Then you can select one of the available dates and make the payment. The interface is very simple and I was able to find a suitable appointment quickly.
The list of appointments for a test center
Taking the exam
The exam center was located a few subway stations from my home and it took me around half-hour to get there. If I had taken it from home I would have needed to install the exam software, test it and check that is compatible with my webcam, so this was not an issue at all.
It was a nice sunny morning as you can see in this photo I took at the subway station exit.
The subway exit
The sign-in procedure was very fast, they asked for my photo ID, took a picture of me, and asked me to sign a form.
Then they guided me to the exam room which was very quiet, comfortable, and had natural light, so it was easy to concentrate.
I got the passing score immediately after completing the exam and a few hours later IBM sent me an email with another badge.
IBM Certified Solution Advisor – IBM Cloud Foundations V2 badge
Overall it was a great experience and I can recommend it to anybody who wants to strengthen his existing skills and learn new things.
Install PHP xDebug with sudo apt install php-xdebug.
Add the following at the end of /etc/php/7.4/cli/php.ini and/or /etc/php/7.4/apache2/php.ini: [XDebug] xdebug.remote_enable = 1 xdebug.remote_autostart = 1
Restart the PHP built-in server and/or Apache HTTP Server.
In the sidebar top, the gear icon will have a red indicator if there is no debug configuration for the project yet. If so, click on it, select the PHP environment if asked and it will automatically create one.
Add a breakpoint by clicking on the left of a line number in your code. A red indicator will appear next to the line.
Click on the green play button at the top of the sidebar. The bottom status bar will turn red indicating PHP Debug is listening for XDebug.
Run the script or load a page in your browser which executes the line where you added the breakpoint line and the execution will be stopped there.
Now you can inspect the environment in the sidebar and continue the execution, continue the execution step by step, stop and pause the script with the bar which will appear over the editor tabs. You can move the bar horizontally by clicking on the first icon.
Recently, we had to create an Interactive Voice Response (IVR) application in PHP using the TwilioTwiML API. Part of this task involved retrieving transcriptions of the called party responses using the TwiML API, so they could be stored in the database. While doing the work, we noticed some aspects that are not mentioned in the TwiML documentation:
Transcription callbacks do not contain session info.
If you set a session cookie for the TwiML calls, the responses will include said cookie, but not the transcription callbacks. To work around this, you can add GET parameters to the callback URL in the TwiML call.
Empty voice responses do not generate a transcription.
When the called party leaves an empty voice response, the transcription callback is not generated. While developing the application we expected to receive an empty transcription, and we spent some time wondering what could be wrong in the code until Twilio Support told us about this behavior.
It seems other developers have also found this confusing, so it’s possible that Twilio will implement callbacks on empty transcriptions in the future.
If you need help with your Twilio application, you can contact us.
Note: this post was approved by the customer. Any potentially confidential information was blurred on the screenshots. Although I did the initial development for this site, I don’t carry its maintenance.
Completed: May 2014.
Kidscerts’ Logo.
KidsCerts allows easy creation of certificates for students and children. The niche market is parents and teachers and it features an user-friendly, easy-to-use interface written in HTML5 and jQuery.
Kidcerts.com home page.
In this project I took on a lead developer role. Our designer did the initial design in Photoshop and converted it to clean HTML5 templates. Then I did most of the coding, with occasional help from a a few freelancers we hired through Freelancer for graphics, rewriting, data entry, and other miscellaneous work.
Project coordination.
As we were a small team and the product owner was heavily involved during the process, we choose Trello for project coordination. Trello has a very intuitive user interface which is pretty straightforward even for non-technical users.
The Trello board we used for this project.
This is a screenshot of the project page (board) in Trello. You can see that there are several lists, each one containing several cards. This gives a quick visual overview of the project. Everything can be rearranged by drag and drop.
The timeline is along the right side. It is convenient to keep track of the progress of the project. You can also receive board updates via email.
A Trello board card detail.
This is the detail of one of the cards, where I discuss an improvement with the product owner. Trello does not have many of the features of other popular project trackers like reporting but we didn’t miss these for this project.
The previous site.
The previous design.
The original site was completly functional but the code and design was done to 90’s standards. It definitely needed a remake. There was little we could reuse from the user interface, so we decided to write it from scratch.
A new design
Here is a screenshot of the initial design made with Photoshop:
The new home page design in Photoshop.
For the form designer, the tabbed input takes less space while being easy to use and visually attractive.
The new create page design in Photoshop.
I really liked the way the designer structured the Photoshop project. He used a single PSD file with well-organized layers, which you can show or hide to see each individual feature.
Photoshop layer tree.
The designer also delivered clean and table-less HTML5 templates:
Our initial HTML template.
Certificate creator user interface.
The user interface required highly customized forms and real-time updates. We used jQuery along with a mix of open source and custom plugins. This was a bit complex due to the amount of integration required but we got it working while achieving a fast and simple interface.
We didn’t find any plugin for this, so we had to develop our own. It’s a jQuery horizontal hierarchical selector with several categories. Each contains several items. We found this very simple to use. It also took up little space.
There are also some frames which require a subscription. When selecting one of these, you will get an interactive tooltip asking you to subscribe. We used Tooltipster for these.
Tooltipster subscribe tooltip.
Text.
For the text inputs only CSS was required. We used msDropdown for customizing the dropdowns.
A jQuery rich text input.
For the font chooser we used jQuery.customSelect. At the time of developing this, we couldn’t find a more specific one for this task. We used images instead rendering the fonts in the browser in order to speed up load times.
A jQuery font chooser.
A customized version of the FontFace jQuery plugin was used for loading these fonts on demand.
For the color chooser, we used jQuery Simple Color. The original script didn’t allow us to use rounded borders for each color item, but the code was easy to customize.
A jQuery color chooser.
Finally, for the multiline quote selector, we used imMultilineList. The possible values are populated automatically as function of the category selector at the left.
A jquery multiline select.
Backgrounds.
Custom backgrounds.
This is very similar to the frames tab. However, here you can also set the transparency level using a slider. We used the jQuery Slider plugin for it.
Registered users can also use custom frames:
Custom backgrounds deletion.
These are stored on the server and can be reused or deleted:
Non-registered users will see the following interactive tooltip:
Custom tooltip for non-subscribers.
Live preview.
Below the form, there is a live preview of the certificate, which is updated as soon as you change anything in the form. This was custom developed.
In the images above, you can see that the live preview is resized automatically depending on the input area height, so its content is always visible.
PDF generator.
The old site had a functional pdf generator written in functional-style php. While a bit outdated for today’s coding standards, it well for the most part. Instead rewriting it from scratch, we decided to clean and refactor it, adding a few new features like the background transparency. Click here to download a sample PDF output.
We also made sure that the differences between the live preview and the pdf were minimal by comparing several screenshots in GIMP. Here is one of these. We made the browser output transparent, and then we placed it over the PDF one:
Checking the rendering differences between the browser preview and PDF versions.
The maximum offset is 4px, due the different font rendering engines. While we could have improved these, we decided to stop here, as most people will not notice such small difference.
Members backend.
Kidcerts.com subscribe page.
We decided to integrate aMember for subscriptions administration and billing. We chose 2Checkout as payment processor as we had positive experiences with it in the past. We skinned the members pages with a cleaned version of the old design. It was working well and looked acceptable so we left it. We will probably integrate it with the new design in a future iteration.
Kidscerts aMember integration.
I can say that I’m happy to have driven this project to completion. Developing such a a complex jQuery interface was challenging, but also rewarding for the entire team. We will probably be adding more features in the future, and I will update this post accordingly.
Java desktop application using Google Chrome to extract eBay item data.
Note: this post was previewed and approved by the customer.
Completion date: February 2015.
In this project, we wrote a Java desktop application to control Google Chrome and extract item data from eBay. Through this method we achieved 100% accuracy.
The “Search URL” input will take a list of eBay search URLs. Clicking on the “Get Item Numbers” button will scrape each search URL and its next results pages, then add the item numbers found to the next input box.
You can add, edit or remove any item numbers in this box. You can even use it without scraping a search page first.
Finally, selecting an output file and clicking on the “Extract” button will extract data from each item page and populate a file in CSV format suitable for Shopify import.
If you need something similar, feel free to contact us.
Several of the projects I’m currently managing, like MockupData and MockupScreens, have complex graphical user interfaces. I have noticed that it’s hard to make this kind of program pixel perfect just by trying to measure the sizes and distances by eye, especially if you have an old/bad/small screen, so here is a small tutorial showing why GIMP should be another of your development tools.
1. Download and install GIMP.
GIMP (acronym of GNU Image Manipulation Program) is open source and completely free. It runs on several platforms, including Windows, Mac OS and Linux. Installation is pretty straightforward: just download and run the installer for your platform in Windows and Mac OS. In Linux, it’s probably already installed; if not you should be able to install it using your favorite software package management utility from your distribution.
2. Take a screenshot of your GUI.
Focus the window you want to capture and then press Alt+Print Screen in windows or Control+Command+Shift+3 in Mac OS. For Linux you can check this site, which also contains more options for Windows and Mac OS. Then, open GIMP and select Edit → Paste as → New Image.
Alternatively, drag and drop an existing screenshot image file into the GIMP title bar, or use the File menu item to open an existing disk file or an image URL.
3. Use the GIMP measuring tool.
Take a look at the following icons. Are these of the same size?
Original buttons.
Let’s use the GIMP measuring tool. First use the zoom so you get a big image on the screen, and then click on the Measure icon in the toolbox, and then make sure the Use Info window checkbox is enabled. Next, left click on the starting point and drag with the mouse to the ending one, then release the mouse button. The distance between the two points will be displayed on the screen:
Measuring the left button with GIMP. Click to enlarge.
Now let’s measure the second one.
Measuring the right button with GIMP. Click to enlarge.
There is a 5 pixel difference. We asked our developer to fix this and make some other changes to the buttons:
Making them smaller, as they looked so big compared to other items in our app. We resized them from 35*26px (left) and 30*26px (right), to 28*22px (both).
Adding 2 pixels between the icons.
Make the font a bit smaller.
Place the plus and minus signs just under the shadow line (this is the line where the background color of the icon changes, thus giving a 3D effect).
Here is the result. You can download and zoom it with GIMP if you want to check the changes:
Fixed buttons.
4. Use the GIMP color picker.
Now let’s look at the following toolbar:
Original toolbar.
Are all buttons of the same color? Let’s check it with the color picker tool. Click on the pointed icon in the toolbox, and then check that the Show info window option is enabled. Click on the background of the Go Screen button.
Using the GIMP color picker on one of the correct buttons. Click to enlarge.
We get a color value of eae8ed. Let’s check the Toggle Comments one.
Using the GIMP color picker on the incorrect button. Click to Enlarge.
Now we get f6f6f2, so the colors are actually different. We also fixed it, and here is how it looks now:
Fixed toolbar.
5. Conclusion.
The appearance of your product is as important as its functionality. With similar features and functionality, a user will choose the one with better appearance, and even if you can’t notice them in your old laptop, people with modern monitors will be able to see them. GIMP allows you to make sure that your GUI elements will look homogeneous to every user with little time and effort, while being completely free software.
Note: this post was previewed and approved by the customer.
In order to post a bid on behalf of the employer in vWorker (adquired by Freelancer on November 2012), he must give me subaccount permissions in his control panel. This is pretty straightforward, and the employer has control over the permissions I will have in his account. To do this, the employer needs to log in to vWorker, go to My account → My subaccounts, click on Add new sub-account and then follow the instructions there.
Once this is done, I can log in to the employer’s subaccount. I use several browsers, one with my main account and others with different subaccounts, so I don’t need to switch the account constantly.
Now it’s time to post a new project by clicking on the Post a new project link at the top left of the page. It’s important to be clear and concise about what you need. On freelance sites like vWorker, a developer needs to place a lot of bids to win a single project, so it’s better to write a small specification on the bid page, and put a full specification in an attachment. Here is a screenshot of the new project page:
Full page screenshot of the vWorker new project page. Click to enlarge.
From four interested candidates, we selected two developers who were in a nearby timezone, communicated well, offered us a reasonable price, and had demonstrable experience with wxPython development.
We started with a small test (fixing a minor bug) using pay for deliverables. In this way the developer has a good idea of what the work will involve and we can know more about his work before starting the bulk of the project. These tests were successful, so we switched to pay for time, as we consider it better suited to agile development than pay for deliverables.
Note: this post was previewed and approved by the customer.
Twilio Logo
Update: One day after publishing this post, Kevin from Twilio suggests in the comments to use the last version from Github instead the 3.2.3 twilio-php library zip archive from the Twilio page. That fixed an SSL certificate validation issue. This is what we call great support!
In a recent project, we used the Twilio REST API to send SMS messages. Here is a very simple tutorial about it.
If you need help integrating Twilio in your application, you can contact us.
1. Register your phone number with Twilio (or get a production account).
At the time of writing this post, Twilio offers a trial account with $30 free credit. Just go to the Twilio site and create a new one. The trial account requires verification of the phone numbers you want to use with their service. You can do this, at no extra cost, by going to Numbers → Verify a number in their control panel. You will then receive a call to that number asking for confirmation.
For your caller ID, you can use the sandbox number you will find after logging in to, buy a number from them or use a verified number. Alternatively, you can upgrade your account to a production one, which will allow you to use any phone number (you have to register a credit card with them, but you don’t need to make a payment until you spend the initial $30 credit).
2. The configuration file
Now, download the twilio-php library from their site (I used version 3.2.3 for this tutorial), or get it from Github and install it in your server (I used the twilio-lib directory). In the root of your site (or in your test dir) create a twilio.config.php file with the following:
Replace the values with the ones you will find after login into Twilio.
3. Send an SMS.
This is pretty straightforward:
require_once("twilio.config.php");
try {
// Instantiate a new Twilio Rest Client
$client = new Services_Twilio($AccountSid, $AuthToken);
/*
* If you get an "Services_Twilio_TinyHttpException: SSL certificate problem [...]";
* exception, uncomment the two lines below. More about this issue at
* http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/
*
* UPDATE: using a twilio-php library version newer than 3.2.3 or the last version
* from Github fixes this issue, making the two lines below unnecessary.
*/
// $http = new Services_Twilio_TinyHttp("https://api.twilio.com", array("curlopts" => array(CURLOPT_SSL_VERIFYPEER => false)));
// $client = new Services_Twilio($AccountSid, $AuthToken, "2010-04-01", $http);
/*
* The number we are sending from, it must be a valid Twilio number
* You can use the default number which you will find in the sandbox,
* buy a number from them or port your own number to Twilio.
*/
$from = "415-599-2671"; // this is the default sandbox number
// The number we are sending to - any phone number
$to = "A Phone Number";
// The SMS body
$message = "Testing the Twilio SMS REST API";
// Send a new outgoing SMS
$response = $client->account->sms_messages->create($from, $to, $message);
// Get the delivery status
echo $response->status;
} catch (Exception $e) {
echo "Caught exception: " . $e->getMessage();
}
4. Check the results.
If everything went well, you will receive an SMS message in your phone. You can also go to Logs → SMS in the Twilio site and see the results there:
Note: this post was previewed and approved by the customer.
Braintree Payments Logo
Recently we integrated Braintree Payments as part of a sales lead routing site project . Here is a small tutorial based on the example we wrote to learn how their API works. Their documentation is great and easy to follow, but we found that it sometimes lacked detail so I had to find some things looking at their (excellent) PHP library source code.
The code is just a quick demo, so it’s far from perfect. However it will be fine for the purposes of this tutorial.
If you need help integrating Braintree in your site, feel free to contact us.
1. Set up a plan in the sandbox.
After signing up with Braintree, you will get an email with your sandbox credentials. For this tutorial, we will create one plan with one add-on.
Go to Recurring Billing → Add-ons and Discounts → New Add-on and create a new one. You should end with something like:
Braintree add-on created. Click to enlarge.
Next, go to Recurring Billing → Plans → New and do the same but selecting the add-on you just created in the step above in the “add-ons” section. You should get something like:
Braintree plan created. Click to enlarge.
Now we can start to code.
2. The configuration file.
You will find the api keys in their sandbox. Just go to Account → My User → Authorization → Api Keys.
Now, download or clone from Github their PHP Client Library (I used version 2.12.3 for this tutorial) and install it in your server (I used the braintree-lib directory).
In the root of your site (or in your test dir) create a braintree.config.php file with the following:
You can do this in separate steps, but in this example we will do at once. Check that I have split the code in several parts, so you will have to join them.
require_once 'braintree.config.php';
$planId = 2000;
$addOnId = 1000;
$includeAddOn = false;
try {
/* First we create a new user using the BT API */
$result = Braintree_Customer::create(array(
'firstName' => 'My First Name',
'lastName' => 'My Last Name',
'company' => 'My Company',
// we can create a credit card at the same time
'creditCard' => array(
'cardholderName' => 'My Name On Card',
'number' => '5105105105105100',
'expirationMonth' => "02",
'expirationYear' => "15",
'cvv' => '123',
'billingAddress' => array(
'firstName' => 'My Billing Address First Name',
'lastName' => 'My Billing Address Last Name',
'company' => 'My Billing Address Company',
'streetAddress' => 'My Billing Address Address',
'locality' => 'My Billing Address City',
'region' => 'IL', // Two letter code
'postalCode' => '60622',
'countryCodeAlpha2' => 'US'
)
)
));
if ($result->success) {
echo("Customer ID: " . $result->customer->id . "
");
echo("Credit card ID: " . $result->customer->creditCards[0]->token . "
");
} else {
foreach ($result->errors->deepAll() as $error) {
echo($error->code . ": " . $error->message . "
");
}
exit;
}
4. Create a subscription.
By default the subscription includes all associated add-ons, but you can remove them using an option.
// Now we create a subscription
$subscriptionData = array(
'paymentMethodToken' => $result->customer->creditCards[0]->token,
'planId' => $planId
);
// The addons are included by default, but we can remove them
if (!$includeAddOn) {
$subscriptionData['addOns'] = array(
'remove' => array($addOnId)
);
}
$result = Braintree_Subscription::create($subscriptionData);
if ($result->success) {
echo("Subscription ID: " . $result->subscription->id . "
");
echo("Transaction ID: " . $result->subscription->transactions[0]->id . "
");
} else {
foreach ($result->errors->deepAll() as $error) {
echo($error->code . ": " . $error->message . "
");
}
exit;
}
5. Modify the subscription.
We add or remove the add-on depending on whether it had been added in the previous step.
When adding it, we can decide if we prorate the addon value. If not it will be charged next month.
This is pretty straightforward. In the last catch the getMessage() method of the thrown exception returns an empty string (a client library bug maybe?).
Go to Search → Subscriptions, click on “Search”, and then select the subscription id to be found in the output of the PHP program. If everything went right, you should find something like this:
Braintree subscription page after running the program. Click to enlarge.