My experience building digital products

digital product

When writing about digital problem solving, I tell stories about past projects. On top of a tech perspective, I also dig into the business, design, marketing, and inter-personal aspects. I’ve been fortunate enough to have a wide breadth of tech experience through my career. It has helped me dive deep into principles and ideas about building digital products. This range of experience was afforded by continually pursuing new work. Finding room for side projects and extra gigs is a great way to grow.

After a daily, hour-long commute I could barely sneak an hour or two for my creative projects and side gigs. But I always did. Side projects were often for paying clients, but sometimes just for fun. They would include not just programming, but also design, marketing, networking, and infrastructure. On top of this, I always made sure my hobbies would serve my overall goals. Reading good books, playing quality games, and being physically competitive all lead to a better life and career.

The key take-away is to work on a variety of projects. Be ready to try different technologies and new platforms. In general, keep trying new things.

Understand infrastructure. Survive some horror stories.

Web infrastructure and hosting setup are skills often missed out on by both casual programmers and professionals. Configuring domain names, email, web hosting, and load balancers is usually reserved for system administrators. Working as one-stop-shop, on your own or in a company, can give you the opportunity to manage all of these details.

I’ve gotten to work with many third-party services and vendors. I’ve seen the good and the bad, and even worse. AWS (Amazon Web Services) has been the best infrastructure provider that I have used. I’ve had horrible experiences from other companies.

Once having had my web servers infected by ransom-ware, HostGator wanted to charge nearly a thousand dollars, to solve the problem. This was the only solution they offered while multiple web properties were infected and out of commission. I fixed the issue myself in less than a few hours by purging all data from the servers and redeploying source code from version control. That was a nightmare.

Another time servers provided by OLM went down for multiple days. This was in 2014. During this time, they wouldn’t answer telephones, letting them ring. I stood on hold for at least 30 minutes, multiple times per day trying to get through. After nearly a week, things started working again, with no explanation provided. That was one of the most unprofessional experiences of my career. I will forever shout them out about this.

Get your hands dirty

Looking forward, I’m excited to explore more of AWS. I’m currently learning through online courses from Udemy: “Certified Solutions Architect” and “Certified Developer”, and plan to take the certification tests. Next, I want to jump into their “Machine Learning” and “Internet of Things” services.

I regularly use AWS services for cloud computing, storage, and databases. My go-to for a new project is to spin up a EC2 instance. If I know I’m using WordPress, I may use a Bitnami AMI. Other times, I’ll create a basic Linux box, and setup Apache, MySql, and PHP myself. Here is the documentation I regularly reference: Install a LAMP Web Server on Amazon Linux 2. This process usually includes configuring a domain name, and setting up SSL: Configure SSL/TLS on Amazon Linux 2.

I’ll continue this post as a series. I plan tell stories about my experiences in building digital products. I’ll cover topics such as design, marketing software, customization, and APIs. Follow me on Instagram for regular updates: @AntPace87

Remove subdirectories from a URL string

javascript

I use GitHub to manage code that I’ll want to re-use. I had trouble finding a canned function to remove the subdirectory path from a URL string – so I wrote one and added it to my latest public repository: https://github.com/pacea87/ap-utils

I’ll keep adding useful code to it – and feel free to make a pull request and contribute yourself. This code should focus on utility functions for manipulating data in interesting ways. Below is the JavaScript code for removing the subdirectories from a URL string. This will also strip away any query string parameters.

function removeSubdirectoryFromUrlString(url){
  
  var ssl = false;
  if(url.indexOf("https://")){
    ssl = true;
  }

  url = url.replace("http://", "");
  url = url.replace("https://", "");
  var pathArray = url.split("/")
  url = pathArray[0];
  if(ssl){
    url = "https://" + url;
  }else{
    url = "http://" + url;
  }

  return url;
}

Now, you can get the current page’s URL, and strip off everything after the host name:

var url = window.location.href;
var baseUrl = removeSubdirectoryFromUrlString(url);
console.log(baseUrl);

Another example:

var url = "https://www.antpace.com/blog/index.php/2018/12/";
var baseUrl = removeSubdirectoryFromUrlString(url);

//This will return "https://www.antpace.com"
console.log(baseUrl); 

I used this code to re-write all URL references in an iFrame to be absolute. My implementation loops through all image, anchor, and script tags on the source site. It determines if each uses an absolute reference, and if not re-writes it as one. This was part of a project that uses a visual editor to allow users to manipulate a remote site. Check out my source code below.

pageIframe.contents().find("img").each(function(){
  var src = $(this).attr("src");
  if(src && src.length > 0 && src.indexOf("//") == -1){  //if not absolute reference
    var url = iframeUrlString;
    if(src.charAt(0) == "/"){ //only do this if the src does not start with a slash
      url = removeSubdirectoryFromUrlString(url); 
    }
    src = url+"/"+src
  }
  $(this).attr("src", src);
});

pageIframe.contents().find("script").each(function(){
  var src = $(this).attr("src");
  if(src && src.length > 0 && src.indexOf("//") == -1){
    var url = iframeUrlString;
    if(src.charAt(0) == "/"){
      url = removeSubdirectoryFromUrlString(url); 
    }
    src = url+"/"+src
  }
  $(this).attr("src", src);
});

pageIframe.contents().find("link").each(function(){
  var src = $(this).attr("href");
  if(src && src.length > 0 && src.indexOf("//") == -1){
    var url = iframeUrlString;
    if(src.charAt(0) == "/"){
      url = removeSubdirectoryFromUrlString(url); 
    }
    src = url+"/"+src
  }
  $(this).attr("href", src);
});

If you liked this, check out my other post about my reusable code framework for web apps, A framework for web apps and startups.

Top 3 graphic design apps for social media marketing

Modern software has given creators the tools they need to showcase their work to the world. Here are the best free apps that I’ve been using that will help your talent shine in 2019:

AppWrap – Do you want to feature your latest website or app design to your followers? Are you building a portfolio for the UI/UX projects you worked on? This app is a great way to wrap your screenshots in a mobile device view. You can add effects, backgrounds, and text to really polish the look and feel. Their template gallery will give you inspiration to make something gorgeous. http://www.appwrap.in/

AntPace.com mobile device view

Canva – This is one of my favorites. With a library of over 60,000+ templates, this app has something for every platform. Whether you need to create a great looking post, story, or cover image, this app has designs for Instagram, Facebook, YouTube and much more. If you want your online presence to look professionally designed, check this one out! https://www.canva.com/

Anthony Pace creativity takes courage

Hatchful – Do you need a logo for your brand, business, or product? This app let’s you create one quickly. By customizing templates, you can draft, and iterate designs. Having logo design done fast, cheap, and easily allows you to focus on the actual product. It’s important to not get hung up on the logo, especially early into your venture, and instead focus on the actual value your service proposes. https://hatchful.shopify.com/

antpace.com

I’ve used all of these apps, and personally gained value from them. What apps do you use for your graphic design?

A template for web app startups

code templates

Having a framework in place when you start up will let you hit the ground running. This applies not just to software, but also business, health, fitness, and just about everything else in life. Having the dots ready to connect helps you to draw the right picture.

I recently released BJJ Tracker as a web app. You can read about it here. I built it knowing that I would want to reuse its code, and have it serve as a framework for future projects. I cleaned it up into a GitHub repository, trying to make it as generic as I could. Here is the link: https://github.com/pacea87/ap-template.

BJJ Tracker

I wanted to create a template to rapidly roll out digital products and software. This source code is a starting point. The goal is to be quick and cheap, without sacrificing quality. It runs in a LAMP environment. If you want to run this software on your computer, look into WAMP or MAMP.

This code base provides a front-end that leverages modern web technologies and standard best practices. A basic layout is described, including a header, menu drawer, feature buttons, and detail pages. It uses Bootstrap, jQuery, Font Awesome, Google Fonts, and Google Charts.

The back-end is object oriented, RESTful, and secure. Code that talks to the database, or to 3rd party APIs, has been separated out into *-service.php files. It includes SQL to create a user database. The database interacts with a custom registration and login engine. It allows for anonymous users, so that data can be saved before signing up, and a password is not needed to get started. It provides a reset password mechanism for users. It seamlessly integrates with Mailchimp and Facebook login. Redirects are in place to force SSL and WWW, and to remove file extensions from URLs. Next versions will address technical SEO and new API integrations.

source code

If you’d like to contribute to this repo, feel free to fork it, and make a pull request.

GitHub

Writing, engineering, and creativity

writing resources

It was 2006 and I had just installed WordPress on a web server. I would draft blog posts nightly, before getting ready for bed. At the time I was a philosophy major and wrote prose more than code. That was my first venture into web development and digital marketing. It started with writing.

Writing blog posts and publishing software have a lot in common. For both, “perfect” is the opposite of ready. It’s easy to keep editing your own work. It’s even easier to keep adding half-done features and clutter. That’s why having a plan before you start helps so much. When I write, my first draft tends to be bullet points and a vague outline. The same goes for software. If I’m building something complex, I write comments explaining its functionality before any code. It’s my way of “thinking out loud”, and making sure that what I plan on doing even makes sense.

It’s been over a decade since I’ve maintained a blog. Creative tasks require hard work, lest they bear no fruit. (“Writer’s block is for amateurs”). Problem solving, in its many shapes, is the highest form of creativity. It’s how we build our reality. Modern technology gives us creative leverage through tools, knowledge, and community. We’re being given opportunities to build and create things, to grow and be better, at an unprecedented scale. It’s the best time in history to be CEO of your own life; creative director of your destiny. This also sets the bar higher to stand out.

My plan here is to write regularly, and discuss what I’ve been working on and learning, as well as what’s next. This gives me a chance to explore my thoughts, and prune the branches from which they stem. Hopefully, working at this will help to make me a better storyteller too. This blog is my notes and stories from the field, on the ground!

BJJ Tracker, a Fitness App

BJJ tracker, a fitness app

www.BJJTracker.com

BJJ Tracker is a fitness app for tracking Brazilian jiu jitsu training. It’s the sort of fitness app I was looking for, but couldn’t find. Version 1.0 is a bare bones MVP, but has a list of features on the way. Future versions will add gamification (including challenges and goals), UX/UI enhancements, training recommendations, and more.

The app allows users to record their training sessions, with details about drilling and sparring, as well as competition. This data is visualized over charts and calendars. The idea started from physically writing my training sessions onto an actual calendar, with a minimum goal per week. Building it has been a great exercise in digital product development, software design, and UI/UX strategy.

fitness tracker calendar

Software

BJJ Tracker is a web app, hosted on a AWS Linux server, running Apache, PHP, and MySql. I used Initializr to generate a bootstrap template to get my front-end started. One goal of this project was to build a web app framework that I could use to quickly get future projects running. This code would include user registration and login services, as well as other back-end concerns, on top of a front-end. I’ve cleaned most of this code into a generic repo on GitHub. You can read my post explaining its features.

Design

This app was designed with “mobile first” in mind, assuming that most users will be on a smart phone. The look and feel of the color palette, font-choice, and UI layout took some experimenting and visual research. It’s not final, and will be subject to split testing over time. I used Font Awesome to add icons as visual cues, giving the app a more finished look. The three lined (hamburger) menu in the top right comes as standard UI, using Simple MobileMenu, a jQuery plugin. Other UI elements include a top status message, and “In-Your-Face” status message, both of which are custom built notifications that I’ve wrapped as javascript plugins. Having a calendar section was important to me, and I consider to be a primary feature of the app. I use Full Calendar to generate the full month view. The homepage (dashboard) focuses on a week view. Google charts is used for the “techniques” graph.

logo design

The logo is a work-in-progress. The textual part was easy – pick a font, add a sharp outline, and a drop shadow. I always start with a 1024×1024 canvas. The symbol begins with simple shapes, triangles and circles. I left this process for last, saving my focus for the actual product. This allowed me to rapidly iterate design versions, and see how it would look directly in the user interface. Below is the current portrayal – and I’m excited for next versions.

BJJ Tracker logo
BJJTracker.com

Full Calendar

Fullcalendar.io has been my go-to solution for adding Calendars to websites. It’s free, and only needs two file references to work (a CSS file and a JavaScript file). You can host those files your self, or use a CDN. And, the UI is easily customized with a bit of <style> code:

<!-- <link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.min.css" rel="stylesheet"> -->
<link href="/css/fullcalendar.min.css" rel="stylesheet">
<style>
#calendar {
    margin: 0 auto;
    width: 100%;
}
#calendar h2{
    font-size: 18px;
}
.fc-scroller.fc-day-grid-container{
    height: auto !important;
}
.fc-button{
    padding: 5px !important;
    outline: none;
    border: 1px solid #2176AE;
    background-color: #2176AE;
    color: white;
    text-align: center;
    box-shadow: 1px 1px;
    border-radius: 6px !important;
    background-image: none;
    text-transform: capitalize;
    font-size: 12px !important;
    height: 25px !important;
    margin-left: 5px !important;
}
.fc-state-disabled{
    display: none;
}
<div class="ap-container top-ap-container" > <div id='calendar'></div> </div> 

<script src="js/vendor/moment.min.js"></script>
<script src="js/vendor/fullcalendar.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.js"></script> -->

<script>

$(document).ready(function() {
	var date = new Date();
	var d = date.getDate();
	var m = date.getMonth();
	var y = date.getFullYear();
	var eventsArray = [];
	<?php
	if(!$view_record_response["record_not_found"]){ 
		$all_record_rows = $view_record_response["all_record_rows"];
		foreach ($all_record_rows as $key => $value){
			$record_date = $value['date'];
			$record_type = $value['type'];
			$rid = $value['recordid'];
			$nameOfDay = date('D', strtotime($record_date));
			$nameOfDay = lcfirst($nameOfDay);
			$color = "";
			if($record_type == "competition"){
				$color = "red";
			}
			?>

			var event = {
			title: "<?php echo $record_type; ?>",
			start: '<?php echo $record_date; ?>',
			end: '<?php echo $record_date; ?>',
			color: '<?php echo $color; ?>',
			url: "view-record.php?rid=<?php echo $rid?>" 
			}
			eventsArray.push(event);

	<?php
		} //end foreach
	} //end if
	?>

	$('#calendar').fullCalendar({
		editable: false,
		events: eventsArray
	});
});
</script>

You can see I get the back-end data through my PHP code (view_record_response), and pass it along on the front-end (eventsArray) to FullCalendar.

Challenges and next steps

One goal of this project was to get started fast, so people could begin using it. Deciding what to include out of a long list of ideas proved challenging. I could have kept adding features, and never been ready to make the site public. I meant to keep functionality basic, but still wanted the thing to be useful. The design needed to be simple, yet still had to look finished. I won’t know how close I came to getting this right until I analyze user feedback. The real plan is to do a little bit better next time, and to keep iterating. Using this as foundation will let future ventures start a step ahead. Already, I’ve begun implementing updates, and getting ready to deploy to the App Store and Google Play. Look out for coming updates and other products that are in the works! Don’t forget to visit the BJJ Tracker blog.

bjj tracker

Interview with a Programmer – Proust Questionnaire

list of questions

The Proust Questionnaire is named after Marcel Proust – the writer. The list of questions was not created by him, but popularized by his answers and eventually resurrected as a common interview guide. I collect questions as a hobby, and these are great additions.

As an exercise in writing, and in thinking, I’ll provide my answers here. I hope you enjoy what I have to say.

  1. What is your idea of perfect happiness? Happiness is like a good cup of coffee – it’s not just about reaching the last drop, but savoring every sip along the way. And if I can share that cup with good company, that’s the perfect blend of happiness for me.
  2. What is your greatest fear? I fear ending up on a deserted island with only a volleyball for company. So, let’s keep the social circles intact, shall we?
  3. What is the trait you most deplore in yourself? I try to keep my inner critic on a strict diet – nobody needs that kind of negativity in their lives. Let’s serve up some self-love instead!
  4. What is the trait you most deplore in others? Selfishness is like a bad haircut – it’s noticeable from a mile away, and nobody wants to be caught sporting it.
  5. Which living person do you most admire? I’ve got a list of virtual mentors longer than my grocery receipt. It’s like having a buffet of inspiration – why settle for just one dish?
  6. What is your greatest extravagance? When it comes to splurging, I’m guilty of treating my taste buds to the VIP section. Fine dining is my weakness, and I’m not even sorry about it.
  7. What is your current state of mind? Picture a sunshine emoji doing cartwheels – that’s my current state of mind: optimistic and doing flips of joy.
  8. What do you consider the most overrated virtue? Patience is a virtue, they say. But let’s be real, waiting in line is overrated – I’m all about that express lane in life!
  9. On what occasion do you lie? Only when I’m auditioning for a role in a spy movie. Honesty is my superpower, but a little white lie can save the day sometimes, right?
  10. What do you most dislike about your appearance? They say beauty is in the eye of the beholder, but if I could change one thing, I’d love to have a built-in snack dispenser. Now, that’s what I call convenient!
  11. Which living person do you most despise? Ain’t nobody got time for hate. Let’s spread love like confetti instead!
  12. What is the quality you most like in a person? Honesty is like a good joke – it’s best when it’s not forced. And a sprinkle of humor? That’s the cherry on top!
  13. Which words or phrases do you most overuse? If my words were a playlist, they’d be on repeat more often than my favorite song. But hey, at least I keep things familiar, right? Maybe in the future, AI can listen to us all day, and give us a weekly digest of how to improve our speech along with a list of overused phrases.

These are my answers, and I hope they help you get a better idea of who I am. One of the most interesting applications of these queries is in fiction writing, to help build realistic characters. Creating worlds with living identities is an art, and characterization questionnaires are a helpful tool in adding depth.

I plan to continually return to this post and update my answers over time.

Bootstrap Website for a Book Author

A vendor (video producer) to the company I worked for, who had is office on the same floor as us, mentioned in the hall way that he had a friend who needed a website. His friend was an author who just had a book published by Simon and Schuster. Joshua Horwitz released “War of the Whales” in 2014. I built his website from scratch using Bootstrap CSS and HTML5 boilerplate. It’s responsively designed, so it adjusts for mobile devices.

I even implemented a custom CMS mechanism, powered by TinyMCE, that was super light weight. It allowed him to update a few pieces of small content through out the site. It used basic authentication, and wrote to a MySQL database.

<script type="text/javascript">
tinymce.init({
forced_root_block : false,
   force_br_newlines : true,
   force_p_newlines : false,
    selector: "textarea",
	  plugins: [
         "advlist autolink link image lists charmap print preview hr anchor pagebreak spellchecker",
         "searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking",
         "save table contextmenu directionality emoticons template paste textcolor"
   ]
 });
</script>

I used some cool visual effects to add animation and make it feel like an immersive experience. The design process took many iterations, but we got it to a place that made sense for the project. The marquee jQuery plugin used the following code:

$('.marquee')
    .bind('beforeStarting', function(){
        
    })
    .bind('finished', function(){
       $('.marquee').marquee("destroy");
	   $(".marquee").css("overflow", "scroll")
    })
   .marquee({
	//speed in milliseconds of the marquee
	duration: 7000,
	//gap in pixels between the tickers
	gap: 0,
	//time in milliseconds before the marquee will start animating
	delayBeforeStart: 0,
	//'left' or 'right'
	direction: 'up',
	//true or false - should the marquee be duplicated to show an effect of continues flow
	
	//pauseOnHover: true
})

Project proposal

Looking back at the original agreement, this is what be planned before the project began:

I will provide two initial design direction samples. You can choose either direction, request changes, and/or combine elements from each sample. Prior to this step, you can send me examples of what you would like your website’s look-and-feel to be similar to, as well as any other specific requests regarding functionality, style, and layout. Following this, we can go through up to two more rounds of revisions regarding the style, layout, and functionality of your website. You will provide any information, text, and images (photos, logo, etc.) that need to be displayed on this website. Any stock images that we may choose to purchase for this website will cost extra.”

It was a fixed price agreement, but I added this paragraph to our documentation:

I know from plenty of experience that fixed-price agreements often limit you to your first idea about how something should look, or how it might work. I don’t want to limit either your options or your opportunities to change your mind. If you do want to change your mind, add extra sections or content or even add new functionality, that won’t be a problem. You will be charged an hourly rate.”

UI Component Pattern for a Simple PHP website

PHP UI component patterns

Reusable components are a staple of modern front-end web development. On my simple PHP website, I wanted to build user interface pieces, and reuse them across multiple pages. When I was creating a new page for a newsletter signup form, I realized that I was repeating a lot of code for a contact form section that is displayed on almost every page.

Contact form section

This website is so simple, it does not use any modern framework. The contact form itself is powered by AWS SES.  I created a directory in the root folder of the website called “components”. There, I put files containing HTML, CSS, and JavaScript code that would otherwise be repeated. Implementing this pattern will help my code adhere to the DRY (don’t repeat yourself) principle, and make it quicker and easier to make changes in the future. Centralizing code ensures quality and scalability.

UI component directory

Searching the code base for references to this particular HTML revealed ten instances that could be cleaned up.

searching a code base

In the new component file, I copy and paste my HTML and CSS code.  Then, I go through each of the offending files, and replace the markup with a reference:

<?php include $_SERVER["DOCUMENT_ROOT"] . '/components/contact-section.php'; ?>

I also delete any CSS and JavaScript for this section that’s on the page. At first, I tried adding the JavaScript that controls this form’s functionality to that same file. It failed because it relies on a jQuery reference that is not loaded until lower in the document. Separating the JS code into its own file, similarly named as `contact-section-js.php`, and calling it below the library reference solved the issue. That code is responsible for passing the message along to the back-end, handling UI success/error notifications, and implementing CAPTCHA to thwart bots. Since it was a lot of files were morphed, I ran a quality assurance protocol to ensure nothing broke.