Deploying Angular 8+ to Azure

I’m really enjoying Angular and Azure, but getting them to work well together is sometimes a pain. Right now, there’s some real catch-up that Azure App Services needs to do in order to embrace anything beyond Angular 7.

That’s because Angular 8 and up (“Angular 8+”) requires Node 12.x, and the latest version of Node.js that Azure App Services supports is 10.6.0. As a result, you cannot do a “build” of an Angular 8+ App on Azure.

Angular is moving rapidly, and they’re already in 9.0 pre-release. I’ve recently moved my own projects to Angular 8.

And I’ve sadly discovered I cannot currently use the standard “Deploy from Github” method to deploy Angular apps to Azure, because the build (which takes place on Azure, using this method) will fail, with an error that the version of Node.js is too outdated. And no, you cannot easily install new versions of Node.js on Azure App Services, because one of the design goals of that App Services platform is to have a curated set of known services, not a “free machine in the cloud” that you can install anything and everything to. You can certainly choose different versions of Node, but you cannot choose anything compatible with Angular 8+ at this writing.

That’s a shame, because continuous integration is a really nice feature of Azure. With it, you do a simple check-in and push to GitHub on a designated deploy branch (I usually choose “master” for this purpose), and then Azure fetches the build from GitHub, does the build locally on your App Services instance, and, with the right tweaks to your deployment script, copies it to the right directory. (Such a build-and-deploy custom script is covered in a prior post on this blog.)

Yes, I could try dockerizing everything, but I really don’t want to do that. I prefer not to have docker always running on my dev machines, and for most of my smaller projects, it’s overkill, because I’m just deploying a Single Page Application and one API.

So, Back to FTP

In the meantime, I’m resorting to simple, tried-and-true FTP deployment with a little automation help from Python.

Remember, all Azure really needs is the contents of your “dist” folder, which is built with the command: “ng build –prod”.

I’ve written a simple python script to do the (Angular 8+) build locally on my dev machine (after testing locally of course), and then it will automatically deploy it via FTP succeeds. Since most of my Angular apps are pretty small (and I like to have a single Git repo with the API back-end and Angular front-end), the process completes far faster than the Continuous Integration approach. I wouldn’t recommend this for large-team, large-scale projects, but it works very well for smaller and especially solo projects.

I expect that eventually, the Azure team will upgrade the versions of Node they support to 12+. When that happens, I’ll likely switch back to Continuous Integration deployment.

If you’d like to go the “build locally and FTP the final ‘dist’ site” route, save this file (called into your Angular app’s “src” folder:

# this file is called 

import os.path, os
from ftplib import FTP, error_perm

host = ''
port = 21

ftp = FTP()


# set filenameCV to your full, absolute path to the "dist" folder 
# of the completed build on your local machine when you do
# an "ng build --prod"

filenameCV = "c:\\build\\your-project-folder\\dist" 

def placeFiles(ftp, path):
    for name in os.listdir(path):
        localpath = os.path.join(path, name)
        if os.path.isfile(localpath):
            print("STOR", name, localpath)
            ftp.storbinary('STOR ' + name, open(localpath,'rb'))
        elif os.path.isdir(localpath):
            print("MKD", name)


            # ignore "directory already exists"
            except error_perm as e:
                if not e.args[0].startswith('550'): 

            print("CWD", name)
            placeFiles(ftp, localpath)           
            print("CWD", "..")

# first, do the build locally 
buildResult = os.system("ng build --prod")

# if there is an error, stop 
if (buildResult==1):

placeFiles(ftp, filenameCV)


To run this script, once you’re ready to deploy your local build, you just issue:


Note that you will get a “cannot rmdir <directory name>” error during the build if you happen to have the project open in another window (say, a manual FTP client.) That’s because “ng build –prod” first wants to clear-out the dist directory, and it cannot, if you have the window open in another application.

Introducing ALIGNVOTE

Ever wish you had help discovering which candidates agree the most with you? Simply answer a few questions, and ALIGNVOTE will tell you. It’s free, quick, and it works easily on your phone or desktop.

Are you a Seattle voter? There’s a very important City Council election coming up on August 6th. Seven of nine spots on our City Council are up for election:

  1. Visit
  2. Point to where you live
  3. Answer a few questions
  4. See which candidates answered most similarly to you to these same questions

That’s it. Pretty simple concept, right? Kind of a self-driven endorsement tool, where you, and not some third party editorial board, are doing the sorting based upon answers and weightings of issues to you, using the candidates’ own responses to the same questions.

Snapshot of the nascent site, as of 6/9/19 at noon PST

We do not endorse candidates. You should.

Please go check it out, see if it works for you.

And then, if you’re interested in the backstory and even a little kerfuffle drama, read on. I’ve also posted about me, the sole creator of the project.

Why? Lowering the Barriers To Connect, Decide and Vote

Just three in ten (30%) of eligible voters cast a vote in some Seattle districts in the 2015 City Council primaries. Think about that. Is that a healthy democracy? 7 in 10 sit it out, even though 100% are affected by the decisions made by the people elected. Year after year, those who cast ballots tend to skew older and wealthier than the general population. Is that a good thing? Why don’t more people connect and vote?

What if it could be made easier for all to identify candidates who most share the perspectives as you do?

Try this test: Can people around you name more than two people running to run our city in the election to be held less than 60 days from now? Can they name one or two who most align with their views? Unless they’re a highly involved voter, or an activist for a specific set of causes, they are very unlikely to know.

But ask the same voter to share their perspective about a City issue, and many more citizens will happily share their opinion, and it may even be strongly held. Well, with a few hours of research, it’s certainly possible to take one’s policy views and map that into some kind of candidate-match ranking. But how many citizens want to invest that hour? And do we really want to continue to entrust the recommendations to the proxy bloggers or editorial boards, whose objectives and perspectives may be far off from our own?

Bridging that gap, and connecting the busy voter with the top three candidates that most align with their own views, yes even controversial ones, is what ALIGNVOTE is all about.

People are busy, and crowded fields, while great for variety and choice, add complexity when voting day arrives. Worse, there’s very little common basis for comparison, unless you attend all-candidate forums where they’re all posed the same question. Or, more accurately, there is usually common bases for comparison, but they’re buried in answers given at all-candidate forums or endorsement questionnaires or the like.

While I wasn’t able to find Seattle-specific data, nearly twenty years ago, MSNBC set out to try to find out why so many eligible voters sat out the 2000 Presidential Election. “Too Busy” ranked as the number one reason people gave:

That’s for a presidential election. I think Democracy works best when more people participate, and I’d like to see voting percentages go higher. If ALIGNVOTE has one objective, it is to help eliminate more excuses for not voting. I do not care if it helps more people who I disagree with on certain issues vote more — that would be a success. I want more people of ANY political opinion to connect more with the candidate(s) of their choosing, perhaps donate or give Democracy Vouchers (a largely Seattle-specific idea) if they are so inclined and able. But above all, vote, even in the primary, and even in August.

I’d like to see if this is a year we can lift that voter participation from 30% to something higher.

As for the issues themselves, I’m of the adamant belief that good, intelligent and well-meaning people can and do disagree on controversial and important issues. That’s why, in most cases, issues escalate to become roiling controversies. Controversies rarely exist because people on one side are “good” and the others “bad”, it’s because there are very real trade-offs at stake, and very different and deeply held philosophies about the proper role of government in our lives. That debate is as it should be; that’s part of democracy. If the answers, impacts or solutions to complex problems were simple, they’d have been solved long ago.

But that leaves us with a problem. How, particularly in crowded fields, can we most easily identify the handful of candidates who align with our perspectives?

You can’t really Google “Which candidates most align with me on transit and zoning tradeoffs?”

Perhaps you’re a voter who, like me, thinks it should be easier to find those top three or so candidates you most align with on the issues you care about for further exploration. Or maybe you’re really sold on a candidate, and want to do a quick double-check if you’re mostly or enough in alignment on other issues… or maybe you’re open to the ideas that your ideas need adjustment.

There’s no shortage of public stances and statements made by candidates. But most people cannot possibly have time to attend every forum, every candidate meet-and-greet, read every Twitter feed, nor read every endorsement questionnaire they file.

It’s Just One of Many Tools

Fortunately, there are forums, venues, campaign events, campaign websites, endorsement questionnaires, meet-and-greets and more. You should get engaged. You should reach out. And to help with that, ALIGNVOTE links you to the campaign websites of each candidate who participates, and we’ll be adding links to resources to help learn more.

It’s just one of many tools, never intended to be the only tool. ALIGNVOTE can and will on occasion highly rank a candidate for people that individual voters feel, for other reasons, are disqualifying. It’s imperfect.

Thanks to public in-person forums, Twitter statements online, campaign websites and more, publicly posted endorsement questionnaires, and yes, surveys sent to candidates, information on top-line stances are out there. What if there were a way to encourage candidates and voters to answer the same questions and then provide information on how aligned they are? Might something like that save time?

ALIGNVOTE is in its infancy, and it will be interesting to see how useful voters find it. As with any beta product, there are bound to be things to improve, and we want to hear your ideas. Please jot us a Tweet.


ALIGNVOTE is far from perfect, nor I suspect will it ever be. But before blasting it for being imperfect tool, please show me the perfect political research tool.

Still, there are very reasonable and rational critiques of this approach. I’d like to respond to some of them here:

On the Multiple Choice Format

No one who has ever taken the SAT has ever loved a multiple-choice format, and I’m not here to defend it as the best way to explore the many nuances of every issue. But such questions provide a useful filtering role, particularly if candidates and voters answer precisely the same question.

Two candidates have written in to suggest that we offer a chance to elaborate upon why an issue was their choice and we totally agree that’s a great idea. We’re currently trying to figure out how to enable that in a way that doesn’t attempt to “swing” the voter during the interview. We may very well provide a way for participating candidates to elaborate upon, or even link off to their more in-depth perspectives or website to explore a topic in a future release.

On the Wording of Questions

Questions were taken from public forums and venues. The phrasing of those questions may seem awkward at times, but that’s usually because that’s how the question was put to candidates in public forums, and we didn’t want to put words in a candidates’ mouths. Throughout, we are making reasonable, best efforts to accurately portray a candidate’s stance, and sometimes that necessitated boiling stances down to “Support”, “Sometimes” or “Never”, but that made it very clear which bucket each public statement fit into. Of course, the best insurance is to actually directly email the campaigns themselves the precise wording of the question, and thankfully the response rate was tremendous in just a few days (thank you, candidates!)

All candidates were emailed the survey last week. They were invited to double-check or in some cases offer up their answers for the first time to the questions posed.

We would be delighted to add more questions if candidates are willing to answer more. To that end, candidates were asked to craft and their own good and fair question with multiple-choice answers in the very survey they’ve already been emailed and responded-to.

On the Listing of Candidates

The list of candidates and contact information was taken from The Seattle Election Commission public disclosure website. A few never registered any email address with the Election Commission, and we were unable to reach them, but happy to do so if they read this and are properly filed. (Contact us.) And, as candidates officially drop out or don’t meet eligibility requirements, we will make efforts to remove them from the result list. There may be some lag in this, as we are relying upon the City of Seattle’s update to their website.

On the Coverage of Issues

Another shortcoming: ALIGNVOTE certainly doesn’t cover all issues, nor does it always frame the question in a complete way. But then again, does any newspaper article, blog post, debate or public speaking event fully frame or explain the nuances of every (or even any) issue?

Remember, candidates and voters answer precisely the same question.

We will happily add more questions in future rounds, and ALIGNVOTE asks each candidate to submit their own topical question for consideration in future rounds. We’ve got some good suggestions in from candidates. As indicated in the About ALIGNVOTE section, we source candidate answers from their public statements, which include their campaign websites, what they state in forums, what they say in public speech, what they write on Twitter, and more. We also directly email all candidates the survey so they can answer in their own words.

Here’s How To Add a Question

It’s early days; the platform just went live last week. So it’s hard to know everything or where this will go. But we are very open to adding more questions over time, if we can get a significant majority of candidates in a given race to answer the same question as worded.

For instance, new “lightning round” questions might be posed at all-candidate forums, and those verified asks and answers might well be added to the ALIGNVOTE survey. Candidates were also offered a space to suggest a good and fair question in their own ALIGNVOTE survey last week; the chances of those getting into the survey are greatly improved if a sizeable percentage of candidates in the race agree to answer it. If candidates can get agreement among other campaigns to ask and answer a common question with consistent multiple-choice answers, we would be delighted to look at adding it.

Candidates: You Can Opt Out

ALIGNVOTE definitely does not wish to force any candidate to participate. You can refuse to participate.

Let me be clear about what opting-out means. All filed candidates will still be listed, so your listing will not be removed. That’s because many voters who know you’re in the race might wonder why your listing is missing, and might consider it a bug or an oversight.

Should you choose to opt-out, your candidate profile box will still appear for all voter alignment interviews for the election race you’re participating in (this will grow well into the thousands as the election date approaches), but your profile listing will be shown as unranked and “refused/opted-out”, and be listed at the bottom of all ranking results. The low ranking is simply because your stances on the issues will officially be blank, and treated as unknown by the algorithm, and no “match” between your views and the ones the voter has expressed can of course be made, so your ranking will be very distant from any view expressed by a voter. If you would prefer not to participate, simply email us from the official campaign email address filed with the City. Our email address is in our About page.

We reserve the right to clearly explain to voters who may be disappointed that you decided not to participate, and encourage them to let you know if that’s something they’d like you to do. Just as is often done in public forums, we will make it clear that you were invited to participate and chose not to.

We also do plan to implement a feature whereby candidates can offer a short elaboration or explanation or perhaps link to policy-explainer on each question posed. This is not yet implemented, solely because of development schedule, not because we don’t wish to do so. This idea came to us from a candidate and we think it’s a great idea. Please note that only participating candidates who have filled out a survey and are participating will be offered this feature. In addition, any future features offered to candidates (e.g., perhaps voter count data on how many “top 3” matches you earned over time, or perhaps contacts directly from voters who indicate they want to know more, etc.) will only be offered to participating candidates. Participation is free; there is no fee.

That is to say — ALIGNVOTE is an ongoing and growing opportunity to connect with voters.

I apologize for keeping my own identity and involvement opaque until now through the data confirmation stage. Most of you have confirmed (thank you) your public views which are already on record, which constitutes the basis of these interview questions. I ask you to stay with us as we build and grow this platform, because I think it benefits voters most of all, but all of us ultimately.

Origins of the Idea: Getting Asked “Who Should Get My Vote?”

…and being unwilling to answer without knowing more.

As I’ve written about in the past on this blog, I spent much of springtime 2019 freely volunteering my time and equipment to record, broadcast and index seven different civic forums for SPEAK OUT Seattle. These free and open events happened across the city, in each of Seattle’s seven different city council districts.

I wanted to hear from and learn more about each candidate’s position. I learned a lot. Live-streaming and A/V was my volunteer role in these forums, and I’m grateful to have the opportunity to do so. All candidates were invited. And the vast majority of the questions — well over 70% — came from the audience in attendance. They were free and open to all. At this stage, thousands of video views have happened on these forums, they got wide coverage and replay in the media, and we’ve been complimented frequently on the professionalism and fairness of these forums.

And here’s what happened in my life in the weeks during and since.

Dozens of friends and contacts have asked me whom to vote for. But good people disagree on different issues and priorities, and it’s not my style to immediately tout people they must vote for, only look into or consider. Also, I generally like to first ask a few questions in these one-on-one interactions about how they feel about particular issues and tradeoffs, and then I point them to the candidates they might want to take a closer look at. That’s because I don’t always know where they stand and the weightings they place on certain issues.

Such interactions inspired me to see if there’s a better way to help identify “matches” between candidate and voter.

On Input from Various People

ALIGNVOTE is independent, and entirely my own creation — that includes the initial idea to build it, the actual coding of the platform, the design (such as it is), the choice of initial questions (largely driven by existing, already public Q&A where stances were made clear), the workflow, the hosting, the operations, the logo, color scheme, brand name and more. It was a significant undertaking over the past few months, but I’ve bootstrapped websites before, and this isn’t my first rodeo in that regard.

As would any builder, I did run it by a variety of sources to get feedback once it was initially publicly viewable. This started about two weeks ago, around the week of May 25th 2019 or so. Those providing input include but are not limited to a former mayor, multiple tech leaders I know, six City Council candidates, former b-school classmates, former Microsoft and Expedia colleagues, fellow volunteers at SOS, and one or two personal friends and family.

As mentioned here and elsewhere on this blog, I do volunteer for Speak Out Seattle (SOS), a non-partisan citizens group where civil discourse is welcome, and which seeks effective solutions to regional issues.

A couple of leaders of SOS first saw this tool two weeks ago, in late May 2019, when I sent them a link of the ready-to-go site for feedback. That was the first time they saw it; a couple weeks ago. None of the comments received from any person or entity involved the selection of, changing of, or altering questions, because by design, most of them were drawn from public forums, where candidate statements are already on the record. People I ran this by had no input on which questions were chosen.

I also ran it by a couple City Council candidates late last week right after the surveys were emailed to all reachable/registered campaigns (and thus other candidates saw it simultaneously. No City Council member influenced the choice of questions either.

One candidate did quite clearly reply back to me to request information on who was behind ALIGNVOTE, and indicated she wanted to know before answering. I replied via email the following day without naming myself, giving her the accurate information that I’m an independent voter in Seattle and that ALIGNVOTE, the project, was unaffiliated with any political party or campaign. I also indicated on the website in the About section that while ALIGNVOTE is organizationally independent, it was built by a human and that human (me) does indeed have political opinions. No one from “Safe Seattle” was ever shown this tool in preview form, nor have I yet discussed ALIGNVOTE with leaders of that media site as of this writing, Monday June 10, 2019.

ALIGNVOTE has a very modest budget at present, which I pay for entirely out of my own pocket. I am the sole director of the project, and we do not make (or seek) any revenue or external funding at this time.

So in sum, schedule-wise: emails were sent to candidates the middle of last week (Weds, Thurs and Friday, as these campaigns were entered into the system), candidates chose (or not) to participate based on the level of information provided, and my identity is now known on Monday.

What’s Next

Now that the beta is out, ALIGNVOTE is already being contacted by other organizations that might want to use, promote, invest in or repurpose the tool.

It’s my view that candidate-finder and alignment tools have use in pretty much any democratic election at the municipal, state or federal level, and that this is more of a “platform” with software behind it which allows groups to author questions and get candidates and voters answering them. So its ambitions may start with the Seattle City Council race of 2019, but will likely go beyond it. (At present writing, I’d really love one now for the crowded Democratic primary race of 2020.) I designed the platform to be repurposable and as automated as possible. There’s a fair amount of work in the back-end which allows the races to be set up, content managed, etc. My initial project is here in the city of Seattle, but I can definitely see this being useful and licensable to other civic or media organizations who want to author their own “candidate matchmaker” services in their own local races. But that’s not yet happened; small steps today.

We will remain financially and organizationally independent of other groups, but our platform has already been, and very well could be (and I hope will be) linked-to or promoted by other media organizations or election groups in the future. It’s the Internet after all, and free websites are only a click away. We will not be preventing anyone from linking to our site.

There will be some great ideas for new questions, and we’d love to hear them. Jot them to alignvote[at] But keep in mind that unless ALL candidates answer these questions, ideally with some support in public venues, it may not make the cut. I could envision some kind of question upvote/downvote before it goes live. Dunno. Lots of thinking to do there, and it’s simply limited by time.


Whew! That’s a lot of information above, and if you’ve read it all, I thank you for your patience.

Like the idea? Please share it on Facebook, Email, Twitter, Nextdoor and face to face with friends and neighbors. And here’s a QR Code that you can put in printed media and flyers:

Got issues or ways to make it better? Please do send in your constructive commentary and feedback! Want to send in a welcome nod of support for what we’re up to? Jot us a note on Twitter. Candidates, if you have any adjustment to your answers or for some reason didn’t get the survey link emailed to you last week, please contact us. Thanks!

Introducing popsee – easy video surveys

Have you ever been to an anniversary or birthday celebration which included video well-wishes from friends and family? Or, have you ever wanted to collect a series of video testimonials from customers?

If you’ve ever tried to gather a bunch of videos from people, you know it’s not easy. It’s a hassle to nudge people, it’s a hassle for them to record a response, upload it somewhere, send you a link. You invariably get it in all kinds of different formats and locations. And nowhere is the information easily sortable, searchable, taggable or organized.

I wanted to do something about that. I’ve launched a new, free tool called popsee which allows you to gather videos easily, from anyone with either a webcam (desktop or laptop) or an iPhone/iPad.

How It Works

Popsee is now in alpha, and only supports one use-case (the townhall described below.) But the basic steps are:

  1. A curator creates a popsee. Think of this as a short video survey.
  2. Curator gets a coded weblink which they can send anywhere
  3. End user following that link can easily respond via webcam and any browser, or iPhone/iPad. There’s no Android app get.) 
  4. popsee does basic validation for you — on things like video length, etc. End-users can re-record clips as many times as they’d like before uploading.
  5. As videos roll in, curator gets a handy dashboard to manage and sort them. Curator can download movies in standard movie formats and edit as they wish.


  • Birthdays, weddings, anniversaries and celebrations
  • Conferences
  • Townhall style forums
  • Product Testimonials
  • Auditions
  • …more

I wanted an easy way for any curator gather and organize videos from a group of people.

Origin Story

A citizen group I’m part of, SPEAK OUT Seattle!, is organizing a series of townhall-style candidate debates for an upcoming city election. As part of this townhall series, I volunteered to film a series of questions from citizens from around Seattle to be projected on the big screen.

When I started to think about the effort involved in driving around Seattle to collect about 80 videos, it dawned on me just how many people have webcams and good-quality smartphones, and that this technology can really help with the sourcing or “audition” process.

Most important, I wanted the tool to be easy. I wanted it to also include simple “metadata” that the curator wanted; in this case, the question in written form, and contact information. 

I was surprised at the lack of tools to allow a curator to initiate a video request from a group of people via, say, a specially-coded weblink (like a shortened URL.)

Sure, you can write an email or do a Facebook post and ask people to record a video and upload it to YouTube and send the link, or maybe put a bunch of videos in Dropbox, but I wanted something point-and-click simple, and I wanted it to optionally include simple survey questions based upon what the curator wants. And when old-style videos do arrive, I wanted them to arrive in searchable format, with “metadata” such as their contact information, email, or perhaps what the subject is. Over time, I’ll be looking at automatic transcription tools, search and indexing tools, word clouds and more. I wanted a platform where a survey-initiator can build a simple survey, with one or more of these questions being submitted by video.

But currently, it’s a Minimum Viable Product ready for some testing.


It’s in alpha testing.

Meaning: it’s being used just for the SPEAK OUT Seattle event.

The free iOS app is in review by Apple and should be available in the next two weeks. This app currently just lets you respond to popsee requests; I expect it will allow you to initiate them some time later this year.

I’ll be building out a great dashboard for the curators, which will include the ability to kick off new requests. If you’d like to try it out, follow and send a DM to @popseea on Twitter.

Learn more at

Send In Ideas

I’d love to hear your ideas and scenarios for requesting videos from people. How can it be made easier for you? Tweet your ideas to @popseeA.

Updating PLEX Media Server

Here’s how to update Plex Media Server on a server running Ubuntu.

Make sure you replace the URLs and packages with the latest release.

  • Find the URL for the latest Plex Media Server package here.
  • SSH into your server. 
  • Download the latest package (replace filename with the latest), then install it:
sudo dpkg -i plexmediaserver_0.–9a47d21_amd64.deb

Following installation, remove the installer file with this command:

rm plexmediaserver_0.–9a47d21_amd64.deb

Remember that you don’t have to type the entire filename, just the first few letters and press <tab> to complete it.