Why and How to Write Good How-To Articles

Part of contributing to any open source project, or even really being a contributing member of any community, is sharing what you know. That can come in many forms. While many projects over emphasis code, and most of us understand the value of conference talks, good how-to articles are some of the most critical contributions for any software platform. There isn’t much point to a tool if people cannot figure out how to use it.

Why do I write how-to articles

I’ve contributed code to Drupal, some of it even good and useful to others. But usually when I hear someone noticed something I created it’s blog posts about how to solve a problem.

When I struggled to find the answer to a question I expect it is a candidate for a how-to post. I am not so creative that I am often solving a problem no one has, or will want to, solve for another project. And I am good enough at what I do to know that if I struggled to find an answer it was probably harder to find than it could been.

That helps me find topics for articles that are helpful to the community and benefit me.

How-to articles help others in the community use tools better

The goal of a good tutorial is to help accelerate another person’s learning process. The solution does not have to be perfect, and I know most people will have to adapt the answer to their project. I write them when I struggled to find a complete answer in one place, and so I’m hoping to provide one place that gives the reader enough to succeed.

Usually I combine practical experience earned after digging through several references at various levels of technical detail – including things like other people’s blog posts, API documentation, and even slogging through other people’s code. I then write one, hopefully coherent, reference to save others that digging extra reading.

The less time people spend researching how to do something, the more time they have to do interesting work. Better yet, it can mean more time using the tools for their actual purpose.

How-to articles serve as documentation for me, colleagues, and even clients

The best articles serve as high level documentation I can refer back to later to help me repeat a solution instead of recreating it from scratch. When I first wrote how-to articles I was solidifying my own learning, and leaving a trail for later.

They also came to serve as documentation for colleagues. When I don’t have time to sit with them to talk through a solution, or know the person prefers reading, I can provide the link to get them off and running. Colleagues have given me feedback about clarity, typos, and errors to help me improve the writing.

I have even sent posts to clients to help explain how some part of their solution was, or will be, implemented. That additional documentation of their project can help them extend and maintain their own projects.

How-To articles give me practice explaining things

One of the reasons I started blogging in the first place was to keep my writing skills sharpened. How-to articles in-particular tend to be good at helping me refine my process in specific areas. The mere act of writing them gives me practice at explaining technology and that practice pays off in trainings and future articles. If you compare my work on Drupal, Salesforce, and Electron you can see the clarity improve with experience.

How-To articles give me work samples to share

When I’ve been in job applicant mode those articles give me material to share with prospective employers. In addition to Github and Drupal.org, the how-to articles can help a hiring manager understand how I work. They show how explain things to others, how I engage in the community, and serve as samples of my writing.

How-To articles help me control my public reputation

I maintain a blog, in part, to help make sure that I have control over my public reputation. To do that I need inbound links the help maintain page rank and other similar basic SEO games.

From traffic statistics I know the most popular pages on this site are technical how-to articles. From personal anecdotes I know a few of my articles have become canonical descriptions of how to solve the problems.

When I first started my current job we had a client ask if I could implement a specific feature that he’d read about in a post on Planet Drupal. It turned out to be mine. Not only was I happy to agree to his request, it helped him trust our advice. My new colleagues better understood what this Drupal guy brought to the Salesforce team. Besides let’s be honest it’s fun when people cite your own work back at you.

Writing your own

You don’t have to maintain a whole blog to write useful how-to articles. Drupal, like most large open source projects, maintains public wiki-style documentation. Github pages allow anyone to freely publish simple articles and there are many examples of single-page articles out there. And of course there is no shortage of dedicated how-to sites that will also accept content.

The actual writing process isn’t that hard, but often people leave out steps, so I’ll share my process. This is similar to my general advice for writing instructions.

Pick your audience

It’ll be used more widely than whoever you think of, but have an audience in mind. Use that to help target a skill set. I often like to think of myself before I started whatever project inspired the article. The higher your skill set the more you should adjust down, but it’s hard to adjust too far, so be careful is aiming for people with far less experience than you have – make sure you have a reviewer with less experience check your work. Me − 1 is fine, Me − 5 is really hard to do well.

Start from the beginning and go carefully step by step

Start with no code, no setup, nothing. Then walk forward through the project one step at a time writing out each step. If you gloss over a detail because you assume your audience knows about it add reference links. You can have a copy of a reference project open but do not use it directly; it’s there to prevent you from having to re-research everything.

List your assumptions as you go

Anything that you need to have in place but don’t want to describe (like installing Drupal into a local environment, creating a basic module, installing Node, etc) state as an explicit assumption so your reader starts in the same place as you do. Provide links for any assumptions which are likely hard for your expected audience to complete. This is your first check point – if there are no good references to share, start from where that article you cannot find should start (or consider writing that article too). 

Provide detailed examples

Insert code samples, screenshots, or short videos as you progress. Depending on what you are doing in your article the exact details of what works best will vary. Copy and paste as little reference code as possible. This helps you avoid accidentally copying details that may be revealing of a specific project’s details.

If you look at mine you’ll see a lot of places where I include comments in sample code that say things like “Do useful stuff”. That is usually a hint that whoever inspired the article had interesting, and perhaps proprietary, ideas in that section of code (or at least I worried they would think it was interesting). I also try to add quick little asides in the code samples to help people pay attention.

Test as you go

Make sure your directions work without that reference project you’re not sharing. This is both so your directions work properly and further insulation against accidentally sharing information you ought not share.

End with a full example

If you end up with a bunch of code that you’ve introduced piecemeal, provide a complete project repo or gist at the end. You’ll see some of my articles end in all the code being displayed from a gist, and others link to a full repository. Far too many people simply copy and paste code from samples and then either use it blindly or get stuck. Moving it to the end helps get people to at least scan the actual directions along the way.

Give credit where credit is due

If you found partial answers in several places during your initial work, thank those people with links to their articles. Everyone who publishes online likes a little link-love and if the article was helpful to you it may be helpful to others. Give them a slight boost.

Salesforce Lightning Web Components with URL Parameters

A couple weeks ago I needed to create a Salesforce Lightning Web Component (LWC) that pulls values from URL parameters. While the process is very simple it turns out the vast majority of examples on the web are out of date due to a security update Salesforce made sometime last year – and so I spent a frustrating afternoon throwing ideas at the wall until a colleague stumbled into a comment on a blog post that was an incorrect example by a highly trusted expert noting the needed fix.  So, in the hopes of shortening the search for anyone else trying to get this to work, I’m offering an example that works – at least as of this writing.

To be fair the official docs are correct but it is easy to look passed an important detail: if you do not put a namespace on your value the parameter will be deleted.

That change was the security update, before that you could have any value as your parameter name now you have to have __ (two underscores) in the name.  Officially the docs say that in the left side of those underscores you should have the namespace of your package or a “c” for unpackaged code. As far as I can tell at least in sandboxes and trailhead orgs you can have anything you want as long as there are characters before and after the __ (which kinda makes sense since package developers need to be able to write and test their JavaScript before they build their package).

So your final URLs will look something like:
https://orgname.my.salesforce.com/lightning/r/Contact/0034x000009Xy5gAAC/view?c__myUrlParameter=12345

Basic LWC

Now with that main tip out of the way on to a full example.

My assumption going into this is that you know how to create a very basic Hello World quality LWC. If not, start with the Trailhead Hello World example project.

1) Create a new component to work with, mine will be very simple to help keep the details clean, but you can fold this into more interesting code bases.

2) Update the component’s meta.xml file to set isExposed to true, and at least a target of lighning__RecordPage (although any target will do if you know how to use it), and configure the target to connect to Contact (although again any settings you know how to use are fine here).

<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
   <apiVersion>50.0</apiVersion>
   <isExposed>true</isExposed>
   <description>Example Lightning Web Componant to read URL parameters.</description>
   <targets>
       <target>lightning__RecordPage</target>
   </targets>
   <targetConfigs>
       <targetConfig targets="lightning__RecordPage">
           <objects>
               <!-- This is setup to run on contact but you could use any sObject-->
               <object>Contact</object>
           </objects>
       </targetConfig>
   </targetConfigs>
</LightningComponentBundle>

3) In your JS file beyond the main LighningElement you need to add imports for wire, track, and CurrentPageReference from the navigation library:

import { LightningElement, wire, track } from "lwc";
import { CurrentPageReference } from "lightning/navigation";

4) Add a tracked value you want to display inside the main class: 

export default class Parameter_reader extends LightningElement { 
  @track displayValue;

5) Next use the wire decorator to connect CurrentPageReference’s getStateParameters to your own code to get an use the URL parameters:

@wire(CurrentPageReference)
getStateParameters(currentPageReference) {
 if (currentPageReference) {
   const urlValue = currentPageReference.state.c__myUrlParameter;
   if (urlValue) {
     this.displayValue = `URL Value was: ${urlValue}`;
   } else {
     this.displayValue = `URL Value was not set`;
   }
 }

From the code sample above you can see that we’re getting the values from currentPageReferences’s state child object, and then attaching them to our tracked value we created in step four.

6) Update the HTML file to display your value ideally leveraging the SLDS along the way:

<template>
 <div>
   <lightning-card title="Url Sample" icon-name="custom:custom14">
     <div class="slds-m-around_medium">
       <p>{displayValue}</p>
     </div>
   </lightning-card>
 </div>
</template>

7) Deploy all this code to your org.

8) Go to a contact record, and edit the page. Add your new competent to the side bar. Save and activate the page.

9) Return to the record page, the component should appear and say “URL Value was not set”.

10) In the address bar add to the end of the url: ?c__myUrlParameter=Hello, and reload the page, the component should now read “URL Value was Hello”.

A screenshot of the sample component displaying the provided text of "hello".

What about sending the value to APEX?

Now, let’s go one step further and send this parameter over the APEX and post a response.

1) Create an APEX class, and create a public static method using the AuraEnabled decorator.

 @AuraEnabled(cacheable=true)
 public static String reflectValue(String value) {
     // Really you should do something useful here.
     return value;
 }

In this case we’re starting with a method that just passes back the same string it was handed, but obviously you can do whatever you want here.

BE CAREFUL ABOUT SECURITY!

If you take an ID as your parameter make sure you are thinking about what happens when someone sends an ID for an object they should not see, is for an object other than the type you expected, and other similar things. The platform can help you but security is your job here, take it seriously!

2) Create good tests for your class, and deploy the code.

3) Import the new function into your JS file:

import reflectValue from "@salesforce/apex/valueReflection.reflectValue";

Update the getStateParameter handler we wrote before to call this function as a JavaScript promise:

  getStateParameters(currentPageReference) {
    if (currentPageReference) {
      const urlValue = currentPageReference.state.c__myUrlParameter;
      if (urlValue) {
        reflectValue({ value: urlValue })
          .then((result) => {
            this.displayValue = `URL Value was: ${result}`;
          })
          .catch((error) => {
            this.displayValue = `Error during processing: ${error}`;
          });
      } else {
        this.displayValue = `URL Value was not set`;
      }
    }
  }

4) That’s it! Deploy your code and reload the page, and your values should pass through to APEX, come back and get displayed.

The complete SFDX project for this example is up on Github.

Salesforce Electron Starter

Back in August I created an Electron project starter that provides a template to use for electron projects with the goal of outlining how to follow the current best practices for writing secure electron apps. I had extracted that from a couple of personal projects I work on from time to time, one of those projects is ElectronForce – a tool to explore Salesforce orgs.  Because I get ideas of things I want to try out from time to time as Salesforce APIs applications I have now created a derivative project that is setup to create apps that leverage JSForce to interact with Salesforce orgs.

Thus I would like to introduce Electron Salesforce Base

Like my generic project starter it is intended to be a jumping off point that handles some of the basic elements of a project.  It’s a bit more opinionated because comes with a little more plumbing in place – there is a simple interface and it’ll actually log into orgs (assuming you have your security token). 

The interface is built using a Bootstrap dark theme from Bootswatch, and is set up to follow the Airbnb ESLint standards (with a couple small tweaks). The interface generates two windows, one that is meant to be the main interface and includes the controls to log into your org, and a second that is meant to keep a running log of events.

The main thread is fully isolated from the render threads, with all requests and data being passed back and forth using the current inter process communication methodology from Electron leveraging the IPCmain object in the main thread and the contextBridge in the render thread – there is no access to remote in the render thread (actually remote is fully disabled as it should be), and the preload.js file largely serves to filter IPC requests to maintain thread isolation. Currently the main thread of this project isn’t what I would call graceful, and I’m actually working on a refactor for ElectronForce to improve the IPC listener definitions (readers with examples of good design patterns are more than welcome to offer suggestions, whatever I settle on will likely get folded back into this project eventually).

To help understand the general pattern that’s emerging as people get better at sandboxing in Electron (and Electron gets better at demanded it) I find it helpful to think of Electron apps in a client-server model with two largely separate applications and a well defined API for communication between them. You’ll see that reflected here, and in my other recent Electron apps. You can implement whatever you’d like in each layer and just pass messages back and forth. This also means you can totally refactor one part of your application without worrying about the other. So if you hate my proto-interface dump it and build something better.

If you look at the code for this base project, then look at ElectronForce, you will see the render thread provides all the details of the interface – including use of render-friendly libraries like jQuery and a collection of helper functions to make life a little easier – makes an API call (with a filter list provided in preload.js), and then handles responses from the main thread. In main.js you see all the IPC listeners defined, which then pass the needed data to JSForce to make the API calls, before handing back structured data for the interface to render.

As you dig through the code you may notice various @TODO statements that are notes to myself about places with obvious room for improvement. I’m always happy to get suggestions, as comments here, issues there, or as pull requests to help resolve those notes with better solutions.

Generate Sample Data for Salesforce NPSP

Snowfakery is a fairly new tool from the team at Salesforce.org. It is designed to generate any amount of arbitrary relational data you can cook up. The Salesforce Open Source Commons Data Generation Toolkit Project has been starting to work on including it in our work (you can read more about my relationship to these projects on the Attain blog) and as part of that, and as part of my actual day job, I’ve been playing with its recipe language, reviewing the documentation, and generally trying to make sure I can use it well.

Snowfakery itself is excellent, but since it’s new there’s a lot of work left to be done on the documentation. The existing docs focus on the generic ways you could use Snowfakery and outline all the features, but I often need it to create very specific things: data for Salesforce orgs with NPSP installed for our nonprofit clients, and the docs aren’t currently great at getting you started at doing that – this post is intended as partial filler in that gap.

The recipe provided here is based on what I’ve learned from my first real successes getting Snowfakery to work on a real-world project.

It give credit where due my first real break through was when Snowfakery’s creator, Paul Prescod, pointed me to a branch in the repo that had some starter NPSP examples. Paul’s samples are helpful but are incomplete and not super well commented. While my solution leverages his work, it simplifies things and takes some short cuts. My goal is functional and understandable, not perfect.

This recipe creates 30 gifts, 20% from companies, 80% from households. They are spread randomly over a set of preexisting Campaigns, and create the needed Accounts, Contacts, Opportunities, and Payments.  It also assumes you are generally comfortable with the major NPSP objects.

This solution is assembled from three files. The main recipe file snowfakery_npsp_basic_recipe.yml for the objects you want to create, and two layered macro files which are used to generate often repeated objects, npsp_macros.yml, and sf_standard_macros.yml. Both are modified from the versions in the example branch of the repo. The Standard Salesforce objects macro file is derived from this one and the NPSP objects recipe macro file is derived from this one.

The code all of them is in a gist, and embedded below (they are numbered in the gist to control display order, remove numbers before actually using). There are inline comments to explain their details. Once you have local copies of all three files (and have Snowfakery installed) you can generate a JSON file that matches the data described:
$ snowfakery --output-format=JSON --output-file gifts.json snowfakery_npsp_basic_recipe.yml

If you are using CumulusCI for your project, you can have CCI load the data directly into your org:

cci task run generate_and_load_from_yaml -o generator_yaml ./datasets/snowfakery_npsp_basic_recipe.yml -o num_records 30 -o num_records_tablename Account --org my_project_sandbox

SC DUG October 2020: Getting Started in Consulting

This month’s SC DUG featured Mauricio Orozco posing questions about getting started as a consultant to long-time members who have all done some work with Drupal as a consultant.

If you would like to join us please check out our upcoming events on Meetup for meeting times, locations, and remote connection information.

We frequently use these presentations to practice new presentations, try out heavily revised versions, and test out new ideas with a friendly audience. So if some of the content of these videos seems a bit rough please understand we are all learning all the time and we are open to constructive feedback. If you want to see a polished version checkout our group members’ talks at camps and cons.

If you are interested in giving a practice talk, leave me a comment here, contact me through Drupal.org, or find me on Drupal Slack. We’re excited to hear new voices and ideas. We want to support the community, and that means you.

RBG Aiken Memorial

Yesterday my wife, Dr. Elizabeth Georgian, and I attended a public memorial for Ruth Bader Ginsburg here in Aiken.

As the constitutional historian at USCA, Beth was asked to speak about Justice Ginsburg’s contributions to the law over the course of her life. Her full remarks are below, followed by pictures I took at the event.

May her memory be a blessing. The Honorable Ruth Bader Ginsburg died on Rosh Hashanah. In the Jewish tradition, that makes her a person of great righteousness. May her memory be a blessing. What that means is not may we remember her to comfort ourselves, but may we remember her through our acts. May we continue her legacy, may we fight for those who are marginalized, may we fight for what is right and just, and may we defend her vision of gender equality, may we will into being her belief that “women belong in all places where decisions are being made.”

Women have been left out of the constitution, once by the framers’ failure to envision women as equal citizens and independent legal beings and then again by the thwarting of the ERA, but Ginsburg fought to make, in that centuries old document, a space for us.

After joining the faculty at Rutgers Law School, she began volunteering for the ACLU. Taking aim at laws ostensibly intended to protect women, she slowly began to reeducate the judiciary about the inherent oppression in such legislation, laws which turned “a pedestal into a cage.” She argued six cases before the Supreme Court between 1971 and 1978, winning five of them.

Reed vs Reed (1971) won women equal rights to administer estates, rejecting an Idaho law grounded in the belief that men were more familiar with the business world and thus better suited to the task. Her brief, a groundbreaking inventory of the law’s oppression of American women, became known as the “grandmother” brief and formed the basis for future challenges to women’s inequality.

In Frontiero v. Richardson (1973) she successfully argued for the right of women in the military to receive benefits for their spouses, just as men did, finding the fifth amendment’s due process clause required the equal treatment of men and women.

Ginsburg recognized that gender inequality hurt men as well as women, an argument she brought before the court in 1975, Wienberger v. Wiesenfeld, when she won the right for widowers, along with widows, to receive social security survivor benefits. More than a legal mind, she cared about those she fought for; after his wife’s death in childbirth, Stephen Wiesenfeld wanted the benefit to stay home and care for their infant son Jason; 23 years later she officiated at Jason’s wedding and 42 years later she presided over Stephen’s second wedding, this time at the Supreme Court. Along the way she presided at many weddings, including the same sex wedding of a former student, aligning with her unfailing support marriage equality, culminating in Obergefell v. Hodges, where she joined with the majority to find in the constitution the right to marriage equality. She presided over her grandson Paul’s ceremony and most recently that of a family friend, a few short weeks before her death.

In a seemingly more trivial case, Craig v. Boren (1976) a case she worked on but did not argue, Oklahoma boys won the right to buy light beer at the same age as girls. In reality, it was an incredibly significant case, one in which seven of the nine justices ruled that the by treating men and women differently, by letting girls drink at 18 but requiring boys to wait until 21, the law violated the fourteenth amendment—granting women significant protection. The case also raised the standard of review of gender discrimination from the lowest standard—rational basis—to intermediate scrutiny, a major, if incomplete step forward.

After joining the Supreme Court in 1993 as the second female justice, in 1996 Ginsburg penned her most significant majority ruling advancing women’s rights, United States v. Virginia, when the court ruled against the Virginia Military Institute’s male-only admissions policy, finding that even the proposed creation of a parallel female academy did not satisfy the fourteenth amendment’s equal protection clause. She wrote that “genuinely equal protection” leaves no room for “a law or official policy that denies to women simply because they are women equal opportunity to aspire, achieve, participate in, and contribute to society based upon what they can do.”

But it was her dissents that brought her fame, and that phrase “I dissent”, along with her affectionate nickname, “the notorious RBG,” came to represent to her admirers persistence in the face of injustice and the dogged belief that standing up for what was right mattered even if the face of seeming defeat. She forcefully dissented in cases threatening women’s access to contraception, called out the men on the court for using “flimsy and transparent justifications” to restrict a woman’s right to choose, and criticized the assaults on democracy made in Citizens United along with the court’s destruction of the Voting Rights Act.

She was never afraid to draw on her personal experiences to argue for equality and fair treatment, pointing out to the men on the court in a case centered on the strip search student, “they have never been a 13-year old girl. It’s a very sensitive age for a girl. I don’t think my colleagues, some of them, understand that.”

As a young woman, she faced open discrimination in the workplace, losing a job for the crime of being pregnant with her first child with the love of her life, her husband Marty. After the Supreme Court ruled that pregnancy discrimination was not a form of gender discrimination, denying women protection, a few years later she helped draft the Pregnancy Discrimination Act, which still protects pregnant women today from workplace discrimination.

In Ledbetter v. Goodyear Tire & Rubber Company (2007), the Supreme Court ruled that, notwithstanding that Lilly Ledbetter was paid less than her male counterparts for 19 long years, she had missed the narrow window to file suit and thus was entitled to no legal remedy. Ginsburg issued her scathing dissent from the bench, accusing her male counterparts of failing “to comprehend…the insidious way in which women can be victims of pay discrimination” and demanded Congress act. Two years later they did, passing the Lilly Ledbettter Fair Pay Act of 2009; a framed copy hung on her office wall until her death.

Ginsburg accomplished so much, finding women and our rights in the fifth and fourteenth amendments, making space for us in a reluctant constitution, raising the bar for gender discrimination, and broadening the definition of equal protection.

But the work remains to be done. The battle for the Equal Rights Amendment, which as she pointed out, every constitution in the world written since 1950 has contained in some form, is ongoing. The Supreme Court still has not embraced a strict standard of scrutiny for sex and gender-based discrimination, the higher standard required to justify racially and religiously disparate laws. And today, the reproductive rights of women, both those free and unfree are under a greater assault than ever before. Ginsburg urged us to “do something outside ourselves, something that makes life a little better for people less fortunate than you,” let us continue the fight in her honor. May her memory be a blessing.

SCDUG August 2020 – “Good Enough” Testing Plans

Drupal SC Logo

This month I gave a talk at SCDUG on encouraging creating testing plans for teams that have been resistant for any number of reasons. This talk is meant to help people argue for the value of testing, and help you create a testing plan that will save more resources that it costs. This was an initial draft of that talk that I’ll be giving a revised and improved version of at Drupal Camp Atlanta in September.

If you would like to join us please check out our up coming events on Meetup for meeting times, locations, and remote connection information.

We frequently use these presentations to practice new presentations, try out heavily revised versions, and test out new ideas with a friendly audience. So if some of the content of these videos seems a bit rough please understand we are all learning all the time and we are open to constructive feedback. If you want to see a polished version checkout our group members’ talks at camps and cons.

If you are interested in giving a practice talk, leave me a comment here, contact me through Drupal.org, or find me on Drupal Slack. We’re excited to hear new voices and ideas. We want to support the community, and that means you.

Simple Electron Starter

Earlier today I push my Electron Simple Starter to Github. It has dependencies only to Electron, Electron Debug, and ESlint (but no specific settings, you can add those yourself). All the basic pieces are in place to encourage good security practices. It will run without warnings or errors, and puts in place all plumbing you need for their current inter-process communication, default overrides, and process sandboxing to help you write a secure app.

Off and on I’ve been playing at writing simple programs in JavaScript using Electron. As a long-time web developer the idea of writing a web app that can be compiled to an native application across a web swath of major operating systems has massive appeal.

But when I started to write Electron apps to scratch various itches, I was quickly annoyed at the number of security warnings I got when following the project tutorials. The PHP community used to ignore bad security in tutorials to the detriment of web, so it bugs me to see that behavior crop up in other places. With my most recent side project – a Salesforce API exploration tool – I finally decided I was overdue in figuring out how to resolve all the warnings the basic quick start from the main project triggers. Using a combination of this secure electron project template and the main project’s security tutorial I finally got there.

Then I wanted to scratch a different itch, which hasn’t really gone anywhere, cause all the work to get started in a secure way felt like a mountain to climb again. The secure electron template is too opinionated for me to use directly for a small toy project, and ElectronForce has all kinds of other code already in place, so I spun my wheels for awhile. Then I finally bit the bullet and extracted the bits I needed for the next project. Once I realized I had a fairly clean baseline, I figured I would probably want it again soon (I create projects frequently to explore an idea or scratch an itch) so I created a new project template that sets the baseline and is fairly unopinionated. My goal is to have something I can grab to start writing a simple application quickly.

While I’ve made some effort to secure this project baseline, security is always the project developer’s responsibility – you are still responsible for your project’s security. Please feel free to use my template, but understand that you still have to follow best practices to keep your app secure and those will change over time. The Electron project will inevitably evolve and change their security system again, and I will not promise to keep up. Also this is a template, not a library, when some future Electron adds features I didn’t use, you’ll need to update your project.

If some specific piece of this template confuses you, please feel free to ask either here or on Github. I can try to explain as best I am able, and maybe you’ll inspire another post sometime in the future to cover it in depth.

SCDUG July 2020 – Drupal in SC State Government

Mauricio Orozco from the SC Commission for Minority Affairs gave a talk about the state of Drupal within the SC State government. In recent years Drupal has grown from a tool used on a small number of projects to the platform of choice for all new agency sites. He spoke about the state’s initiative to move more to Drupal, South Carolina Interactive and their role in supporting government projects, which agencies are moving toward Drupal, and how this is benefiting residents of South Carolina.

If you would like to join us please check out our up coming events on MeetUp for meeting times, locations, and remote connection information.

We frequently use these presentations to practice new presentations, try out heavily revised versions, and test out new ideas with a friendly audience. So if some of the content of these videos seems a bit rough please understand we are all learning all the time and we are open to constructive feedback. If you want to see a polished version checkout our group members’ talks at camps and cons.

If you are interested in giving a practice talk, leave me a comment here, contact me through Drupal.org, or find me on Drupal Slack. We’re excited to hear new voices and ideas. We want to support the community, and that means you.

Protests in America – Black Lives Matter

Over the last few weeks the US has been moved to action about policing and racial justice in response to the murder of George Floyd. As someone who is deeply concerned about these issues I always struggle to find words I feel do the topic justice; they seem too important to stay silent, too critical to speak about poorly, and too complex for me to write about well. For my limitations in what follows, I’m sorry.

As a society we are still working to understand that the violence and murders by police we see played out regularly in the new is not just the fault of the individual officers or their by-stander colleagues, but also the fault of our society as a whole. This has not happened in a vacuum. Our communities have voted too often for people and policies that brought us here instead of doing something better.

But all those are things you can read about in detail from more skilled writers than me. And if you haven’t you should.

I want to talk here more about the fact that we all know we cannot trust the police to handle complex situations, in particular protests. It is why we all set our expectations that it is simply someone else’s job to maintain calm when large crowds are involved with police.

The most basic sign of this lack of trust is that no one doubts the importance of the long-standing understanding among families raising children of color that they must teach very young kids how to de-escalate with police because they cannot trust officers not to shoot a child playing alone in the park. If that’s not something you’ve known was happening for a long time, I recommend Clint Smith’s letter to his then-future son, and more broadly his recent interview on TED Radio Hour. If you are a person of color, a woman, or mentally ill it’s long been clear that society expects you to protect yourself against police officers.

Beyond those seemly obvious, but still debated reasons, we have all long shown we don’t trust police in how we talk about protests. Until the videos of police violence from protests caused a shift in how we talk about these events in the last few weeks we had a very standard story around any riot, protest, or civil unrest which assumed police could not handle angry expressions of the first amendment.

The story starts with a nonviolent march or gathering, and then degrades into a violent riot because of a few bad people in the crowd. The police are be cast as innocent bystanders until the violence broke out, then they became heroes working to regain control for the rest of us. We see these stories on the news and wring our hands about a good message being marred by violence – too bad they didn’t learn Dr. King’s message.

If you have been to a large protest you probably know in your gut that’s not how it works in real life. In practice throughout the day the police are making decisions about how to interact with the crowd. Often this starts with little or no containment during the initial events, then the police start to restrict the group’s movement. They use increasingly aggressive tactics to try to control the physical direction of protesters putting pressure on the crowd they say they want to keep calm. Sometimes they say this is to enforce a permit, sometimes they claim to be protecting businesses, and sometimes they don’t give any reason. When things finally turn angry and violent, the police have made themselves the front line and often starting the actual fighting. There is no actual reason to make this shift in most cases, just things like a sense that protests after dark are more dangerous and the cost of policing.

An anti-Trump march in Philadelphia in 2017, well after their permit expired and out of bounds for the march, but being guided by police not confronted for another hour or two.

We have long criticized marchers for damaging small businesses, burning their own neighborhoods, while ignoring that police and politicians tried to control where protests were held and used force to keep people in their neighborhoods.

A wet older man standing in front of the water cannon truck with lots of younger people on the ground around him.

Reporters, politicians, and police would ignore all the research of large crowd dynamics, and blame the crowd for doing what large groups of angry people do when pressed – fight back.

In the US we started to assume it was the protester’s job to stay nonviolent in the face of extreme police response during the 1960’s and 1970’s when the civil rights and antiwar movements showed it was possible. It is also important to remember that while there were amazing peaceful protests in that period, there were also large riots, rebellions, and general civil unrest. We remember the great example set an inspired few, not the larger contexts of events that unfolded.

Riot police, and other officers in the shade talking with protesters.
The protesters at this event invited the police into the shade and offered them water and fresh fruit. It was meant to help keep the officers calm on a hot day, because we could not trust them to remain calm without our help.

Just because we want large protests expressing anger at our government to be nonviolent that does not mean we can reasonably expect every group to manage the needed level of organization and training to make that possible. We have a paid, trained, group of people we already expect to show up for these events – why don’t we assume they are going to help make sure these events are empowering expressions of our first amendment rights? Why do we assume that the unpaid citizens exercising their rights need to be able to handle situations that police cannot?

Currently our police are badly trained at de-escalation, even though it’s been shown to keep them safer. That training will cost money, but we could cover that by cutting funding of unneeded weapons like armored personnel carriers. I know some people who can run that kind of training – trust me they would do a lot of training for the annual maintenance budget on one of those things.

People at the side of the road with signs that read: No Human Being is Illegal. Families belong together. My Family Came as Refugees. No Heat No Ice. Keep Families together. And other slogans.

Yes, being a police officer is hard. I agree with the many officers complaining that we expect them to do all kinds of things they shouldn’t be asked to do because yes they need better solutions around them. And of course they should expect they will come home safely at the end of their shifts. But just because a job is hard, and can be dangerous, does not make it okay to do the job badly – in fact that seems like an argument to do the job well.

The flaws in our system are not the fault of individual officers – no one officer can reform the system (although any one of four police officers could have saved George Floyd’s life by stopping his murder). No one mayor, police chief, nor any one person has the power to make the kind of change we need to make our communities safer for everyone in them. Everyone is responsible for their own personal behavior, but dismissing gross misconduct including murders as the acts of a few “bad apples” instead of recognizing that they are part of a system that our society built is an injustice in itself.

The system is well past needing simple reforms being debated in Washington and many state legislatures. Maybe if we’d really reformed things after the police riots of the 1960’s, when departments were smaller and officers less protected from consequences, we could have used incremental measures. Now we need drastic sweeping changes. We need to understand that Camden, NJ’s choice to disband and rebuild their department was a first step that shows you’re serious but doesn’t mean you’ve made enough progress. After you totally reboot you still have to be ready to totally rebuild.

Handmade sign reading Are you going bkwds? or are you going fwds?
We are going forwards, we don’t have a choice, the question is where will that take us?