Skip to main content

Blog

We love free and open formats. RSS or Really Simple Syndication is a great way to keep in touch with your favorite blogs and websites.

We have two available:

New to RSS?

If you're new to RSS, here's what you need to do:

  1. Get an RSS Reader
  2. Subscribe to RSS feeds

There are a lot out there. If you'd like to use a web-based reader, one option is CommaFeed. It's free software, easy to use and has lots of features.

If you prefer a desktop application, Raven Reader is also free software and well designed.

Approximate budget.

What are Agaric's initiatives, you ask?

We do much more than build websites. We build tools that work for the social change we want to see. We teach and empower others to use digital technology safely, responsibly, and effectively. We participate in building and supporting communities that are founded on democratic-ownership and knowledge-sharing. We engage in a plethora of movements, and we look for ways to bridge the gaps between them. Akin to the mushrooms after which we are named, we work across vast nutritive networks so that we can bring nourishment to our human ecosystems. This page is our feeble attempt to showcase the meaning behind Agaric Tech Cooperative.

Overview

I. Platforms and Hosted Services

II. Open Community Events

III. Contributions to Drupal

IV. Movements and Networks

V. Auxiliary Tech Projects

 

I. Platforms and Hosted Services

Health communities  

We have been building innovative web-based homes for scientific and health communities since 2008— most recently partnering with the National Institute for Children's Health Quality.

Find It 

The Find It program locator and event discovery platform for cities, towns, counties, and most any geographical community. Use granular search to locate resources that otherwise may be hard to find!

Drutopia

The Drutopia Cooperative Platform by Agaric combines the ease of use you find from software as a service website builders (like Wix and Squarespace) with the freedom and control of free (libre) software.  It is LibreSaaS like Ghost(Pro) or WordPress.com, but it is built for and with grassroots groups.  Importantly, the platform is collectively controlled by the people who rely on it.

Online Learning  

Host your school online. Stay safely at home while learning and interacting with others. We will host your online courses and video chat without connections to Google or Facebook and free from spyware or malware that can go undetected in proprietary software. We are using free and open source solutions that are currently used by colleges and schools around the world. Agaric can build upon these solutions to customize your experience and suit your needs.

CommunityBridge 

CommunityBridge is an online video conferencing service that we provide freely to trusted friends and activists in our network. It is also where we host our community events. The video conferencing software behind it is BigBlueButton, a free and open source software built for educational communities to learn together safely in a digital space without fear of being passively tracked and surveilled.

 

II. Open Community Events

Show & Tell

Agaric hosts a weekly online gathering for people to meet and share what they have learned. Sometimes we talk about the logistics of worker owned Cooperatives and sometimes we have technical talks and we look at code. Every week we also get to know each other better and this leads to sharing work on projects. Learn more about Show and Tell. One of our most popular meetings was a presentation and discussion on a real life condition that affects quite a few developers. This condition is called imposter syndrome.

Movie Night

Agaric hosts Movie Nights, where we support organizations in sponsoring facilitated movie-watching events and engage in deep discussions that sometimes reveal actionable steps that community members can take together to overcome social and political issues. Currently we are only able to watch movies that are hosted on Vimeo, Youtube, or DailyMotion. If you would like to suggest a movie, we will facilitate the event. Make some popcorn, grab your favorite beverage, and invite your friends!

 

III. Contributions to Drupal

Drupal.org.

Drupal is a free software content management system powered by one of the largest communities in the software world— very much including Agaric.

Contributed Drupal Modules

We contribute to Drupal core and more than 100 modules that extend its functionality.  All of these useful projects are free for anyone to download, use or modify for their own needs.

Read about a few of the many many things Agaric contributes to Drupal on our Drupal Give initiative page.

Trainings

We teach development teams and solo coders in-person or online, with the program tailored to the problems you are trying to solve. We have practical experience in developing a multitude of web sites, migrating content, and running technology projects - we love to learn and to teach. We will impart the knowledge and skills you need to get work done, and done right. 

31 Days of Migrations

Mauricio's epic month of migration tutorials is an expansive resource to teach you how to perform Drupal migrations. At some point, almost every website will need to be migrated to a newer or more secure platform, or to a platform with new and different features. Migrating to a new and different platform or server happens for many reasons during the life of a project. Be prepared!

Drutopia

Drutopia is a flexible content management system with many features built specially for grassroots organizations.  It already helps groups share goals, call for action, collect donations, and report progress.  Most important, Drutopia's developers seek to design ongoing improvements and capabilities with groups organizing for a better world.

IndieWebCamp is a movement dedicated to growing the independent web, or IndieWeb: a people-focused alternative to the corporate web. The movement is called IndieWebCamp because it is built in large part over an on-going series of two-day camps. At these camps and online, the community emphasizes principles over particular projects or software— any web site can be a part of the IndieWeb. Here's how to take a first step into the IndieWeb with Drupal.

All the benefits from brewing your own website touted by IndieWebCamp are indeed great. Your content belongs unambiguously and in real and practical ways to you; at the least it won't disappear when yet another company shuts down or is acquired and tells its fans "thanks for supporting us on our incredible journey". Above all, you are in control of what you post, how it is presented, and how others can find it. All this may be familiar to web developers as the concept of "having a web site."

If that was all there was to the movement, IndieWebCamp would be a call to do it like we did it in 1998. Instead, IndieWebCamp goes the next step by recognizing that people use the corporate web of Facebook, Twitter, Tumblr (Yahoo), Blogger (Google), Flickr (Yahoo), LiveJournal (SUP Media), YouTube (Google), and others in large because of the experience they provide for interactions between people. IndieWebCamp takes on the challenge of designing user experiences and formats and protocols which make following, sharing, and responding just as easy on the independent web of personal sites and blogs.

To this end of making social interaction native to independent sites, IndieWeb principles and practice teach a couple of new tricks to old web sites. One of these tricks, which we will not cover today, provides a bridge from independent sites to the monolithic services most people use today by implementing the approach of Publish (on your) Own Site, Syndicate Elsewhere (POSSE). This means that posting on your own site provides an advantage in that your posts and status messages can go to all services rather than get stuck inside only one.

The first steps of getting on the IndieWeb (after joining the #indiewebcamp IRC channel) are very familiar to web developers: Put up a web site. We were all set with a domain name for Agaric and with web hosting, so we could skip right to setting up our home page and signing in.

All you need to do for this step is to add rel=me to a link to an online profile that links back to your home page, identifying yourself in both places as you. In our case, we added the rel="me" attribute to a link to our Twitter profile. Twitter puts rel="me" on the web site link on their profiles. We did have to make sure we linked to Twitter with https not http so that the redirect didn't interfere with verifying our web sign in capability with IndieWebify.me. The link to Agaric's Twitter account on our page looks like this:

<a href="https://twitter.com/agaric" rel="me">Twitter</a>

Next up is giving the independent web some basic facts of our identity using the h-card microformat. I've never heard anyone claim that microformats have the most intuitive names, but all the properties are documented. We edited our page.tpl.php template to add the h-card class to a h1 tag surrounding our logo, to which we added the class u-logo and our site name with linking to our homepage, to which we added the classes p-name and u-url. Again using IndieWebify.me we verified that the h-card could be read. The markup looks like this:

<h1 class="container h-card"><a href="http://agaric.com/" id="logo" rel="home" title="Agaric home"><img alt="Agaric home" class="u-logo" height="80" src="http://agaric.com/sites/all/themes/agaric_bootstrap/logo.png" width="80" /></a> <a class="p-name u-url" href="http://agaric.com/" rel="home me" title="Home">Agaric</a> <small>We build online.</small></h1>

Finally, blog posts themselves are each marked up as an h-entry and elements of each blog post with h-entry properties. (The IndieWebCamp wiki has a stub article for h-entry and the markup IndieWeb makes use of, but we found the h-entry listing on microformats.org to be clearer.) For blog posts' markup we did a lot of work in template preprocess hooks. For example, here we add the h-entry class itself, the p-name class for the blog title, and (with a bit of reconstruction of Drupal's $submitted variable) the dt-published class for the date and time the blog post was published:

/**
 * Implements hook_preprocess_node().
 */
function agaric_bootstrap_preprocess_node(&amp;$variables) {
  if ($variables['type'] == 'blog') {
    $variables['classes_array'][] = 'h-entry';
    if (!isset($variables['title_attributes']['class'])) {
      $variables['title_attributes_array']['class'] = array();
    }
    $variables['title_attributes_array']['class'][] = 'p-name';
    $datetime = format_date($variables['node']-&gt;created, 'custom', 'Y-m-d h:i:s');
    $formatted_date = '<time class="dt-published" datetime="' . $datetime . '">' . $variables['date'] . '</time>';
    $variables['submitted'] = t('Submitted by !username on !datetime', array('!username' =&gt; $variables['name'], '!datetime' =&gt; $formatted_date));
  }
}

Here's the IndieWebify.me validation for this very blog post. The markup looks like this:

<article about="/blogs/marking-drupals-blog-posts-indieweb" class="node node-blog h-entry clearfix" id="node-262" typeof="sioc:Post sioct:BlogPost">

<h1 class="p-name"><a class="u-url" href="http://agaric.com/blogs/marking-drupals-blog-posts-indieweb" rel="bookmark" title="Marking up Drupal's blog posts for the IndieWeb">Marking up Drupal's blog posts for the IndieWeb</a></h1>

<span content="2015-05-04T11:58:16-04:00" datatype="xsd:dateTime" property="dc:date dc:created" rel="sioc:has_creator">Submitted by <a about="/people/benjamin-melan%C3%A7on" class="p-author h-card username" datatype="" href="http://agaric.com/people/benjamin-melan%C3%A7on" property="foaf:name" rel="author" title="View user profile." typeof="sioc:UserAccount" xml:lang="">Benjamin Melançon</a> on <time class="dt-published" datetime="2015-05-04 11:58:16">Mon, 05/04/2015 - 11:58</time></span>
<div class="e-content">…</div>
</article>

What do you think of the IndieWebCamp movement and its goal of making distributed sharing and following easy, while not prescribing which platforms or technologies to use? How about Agaric's far-from-automated approach to making a Drupal site part of the IndieWeb? And do you think Drupal should try to be more IndieWeb-ready as we expect another burst of growth with the release of Drupal 8?

Register for the upcoming partipatory workshop on technology and revolution. The more people that RSVP the better we can prepare for the discussion.

Today we will learn how to migrate dates into Drupal. Depending on your field type and configuration, there are various possible combinations. You can store a single date or a date range. You can store only the date component or also include the time. You might have timezones to take into account. Importing the node creation date requires a slightly different configuration. In addition to the examples, a list of things to consider when migrating dates is also presented.

Example syntax for date migrations.

Getting the code

You can get the full code example at https://github.com/dinarcon/ud_migrations The module to enable is UD date whose machine name is ud_migrations_date. The migration to execute is udm_date. Notice that this migration writes to a content type called UD Date and to three fields: field_ud_date, field_ud_date_range, and field_ud_datetime. This content type and fields will be created when the module is installed. They will also be removed when the module is uninstalled. The module itself depends on the following modules provided by Drupal core: datetime, datetime_range, and migrate.

Note: Configuration placed in a module’s config/install directory will be copied to Drupal’s active configuration. And if those files have a dependencies/enforced/module key, the configuration will be removed when the listed modules are uninstalled. That is how the content type and fields are automatically created.

PHP date format characters

To migrate dates, you need to be familiar with the format characters of the date PHP function. Basically, you need to find a pattern that matches the date format you need to migrate to and from. For example, January 1, 2019 is described by the F j, Y pattern.

As mentioned in the previous post, you need to pay close attention to how you create the pattern. Upper and lowercase letters represent different things like Y and y for the year with four-digits versus two-digits, respectively. Some date components have subtle variations like d and j for the day with or without leading zeros respectively. Also, take into account white spaces and date component separators. If you need to include a literal letter like T it has to be escaped with \T. If the pattern is wrong, an error will be raised, and the migration will fail.

Date format conversions

For date conversions, you use the format_date plugin. You specify a from_format based on your source and a to_format based on what Drupal expects. In both cases, you will use the PHP date function's format characters to assemble the required patterns. Optionally, you can define the from_timezone and to_timezone configurations if conversions are needed. Just like any other migration, you need to understand your source format. The following code snippet shows the source and destination sections:

source:
  plugin: embedded_data
  data_rows:
    - unique_id: 1
      node_title: 'Date example 1'
      node_creation_date: 'January 1, 2019 19:15:30'
      src_date: '2019/12/1'
      src_date_end: '2019/12/31'
      src_datetime: '2019/12/24 19:15:30'
destination:
  plugin: 'entity:node'
  default_bundle: ud_date

Node creation time migration

The node creation time is migrated using the created entity property. The source column that contains the data is node_creation_date. An example value is January 1, 2019 19:15:30. Drupal expects a UNIX timestamp like 1546370130. The following snippet shows how to do the transformation:

created:
  plugin: format_date
  source: node_creation_date
  from_format: 'F j, Y H:i:s'
  to_format: 'U'
  from_timezone: 'UTC'
  to_timezone: 'UTC'

Following the documentation, F j, Y H:i:s is the from_format and U is the to_format. In the example, it is assumed that the source is provided in UTC. UNIX timestamps are expressed in UTC as well. Therefore, the from_timezone and to_timezone are both set to that value. Even though they are the same, it is important to specify both configurations keys. Otherwise, the from timezone might be picked from your server’s configuration. Refer to the article on user migrations for more details on how to migrate when UNIX timestamps are expected.

Date only migration

The Date module provided by core offers two storage options. You can store the date only, or you can choose to store the date and time. First, let’s consider a date only field. The source column that contains the data is src_date. An example value is '2019/12/1'. Drupal expects date only fields to store data in Y-m-d format like '2019-12-01'. No timezones are involved in migrating this field. The following snippet shows how to do the transformation.

field_ud_date/value:
  plugin: format_date
  source: src_date
  from_format: 'Y/m/j'
  to_format: 'Y-m-d'

Date range migration

The Date Range module provided by Drupal core allows you to have a start and an end date in a single field. The src_date and src_date_end source columns contain the start and end date, respectively. This migration is very similar to date only fields. The difference is that you need to import an extra subfield to store the end date. The following snippet shows how to do the transformation:

field_ud_date_range/value: '@field_ud_date/value'
field_ud_date_range/end_value:
  plugin: format_date
  source: src_date_end
  from_format: 'Y/m/j'
  to_format: 'Y-m-d'

The value subfield stores the start date. The source column used in the example is the same used for the field_ud_date field. Drupal uses the same format internally for date only and date range fields. Considering these two things, it is possible to reuse the field_ud_date mapping to set the start date of the field_ud_date_range field. To do it, you type the name of the previously mapped field in quotes (') and precede it with an at sign (@). Details on this syntax can be found in the blog post about the migrate process pipeline. One important detail is that when field_ud_date was mapped, the value subfield was specified: field_ud_date/value. Because of this, when reusing that mapping, you must also specify the subfield: '@field_ud_date/value'. The end_value subfield stores the end date. The mapping is similar to field_ud_date except that the source column is src_date_end.

Note: The Date Range module does not come enabled by default. To be able to use it in the example, it is set as a dependency of demo migration module.

Datetime migration

A date and time field stores its value in Y-m-d\TH:i:s format. Note it does not include a timezone. Instead, UTC is assumed by default. In the example, the source column that contains the data is src_datetime. An example value is 2019/12/24 19:15:30. Let’s assume that all dates are provided with a timezone value of America/Managua. The following snippet shows how to do the transformation:

field_ud_datetime/value:
  plugin: format_date
  source: src_datetime
  from_format: 'Y/m/j H:i:s'
  to_format: 'Y-m-d\TH:i:s'
  from_timezone: 'America/Managua'
  to_timezone: 'UTC'

If you need the timezone to be dynamic, things get a bit harder. The from_timezone and to_timezone settings expect a literal value. It is not possible to read a source column to set these configurations. An alternative is that your source column includes timezone information like 2019/12/24 19:15:30 -07:00. In that case, you would need to tweak the from_format to include the timezone component and leave out the from_timezone configuration.

Things to consider

Date migrations can be tricky because they can be affected by things outside of the Migrate API. Here is a non-exhaustive list of things to consider:

  • For date and time fields, the transformation might be affected by your server’s timezone if you do not manually set the from_timezone configuration.
  • People might see the date and time according to the preferences in their user profile. That is, two users might see a different value for the same migrated field if their preferred timezones are not the same.
  • For date only fields, the user might see a time depending on the format used to display them. A list of available formats can be found at /admin/config/regional/date-time.
  • A field can always be configured to be presented in a specific timezone. This would override the site’s timezone and the user’s preferred timezone.

What did you learn in today’s blog post? Did you know that entity properties and date fields expect different destination formats? Did you know how to do timezone conversions? What challenges have you found when migrating dates and times? Please share your answers in the comments. Also, I would be grateful if you shared this blog post with others.

Next: Migrating addresses into Drupal

This blog post series, cross-posted at UnderstandDrupal.com as well as here on Agaric.coop, is made possible thanks to these generous sponsors. Contact Understand Drupal if your organization would like to support this documentation project, whether it is the migration series or other topics.

Climate Crisis Clock.

The ever intensifying climate crisis is an existential threat. It was brought upon by people designing and building technology reliant upon the extraction and burning of fossil fuel. That and an economic system reliant on ever increasing consumption, demanding energy production unsustainable to the planet.

From September 20th through September 27th millions of people across the globe skipped school, walked out of workplaces, and joined in the streets to demand bold, swift action for climate justice. Many in the tech industry, including ourselves, went on digital strike, shuttering our websites for the day to join in the action. In fact, we partnered with 350.org to improve the mapping tool used to help people organize and find climate strike actions.

But what does bold, swift action mean? What is required of us to respond to the enormity of this climate catastrophe?

One thing is for certain - it won't be fixed with the same values, systems and forces that ushered in this emergency.

There are many ideas out there on what we should do, with many different names. Whatever the specifics, the path to climate justice rests on our ability to move away from extractive relationships with our earth and quickly grow regenerative relationships instead. Many are calling this the Commons Transition. Those of us working in the tech industry have tremendous influence in participating in and assisting with this transition.

What is the Commons?

The Commons is a way to organize and manage resources collaboratively among the community of producers and users. They exist outside of both the public and private sector. The commons is flourishing all around us, particularly where indigenous communities have been able to defend themselves and their land. The Zapatista caracoles in Chiapas, Mexico, the confederalist communes of Rojava, and the Potato Park in Peru are just a few examples. All are a blend of retaining generations-long wisdom of living in right relation, an unlearning of the extractive patterns that have gained dominance, and innovating new ways of commoning.

Zapatista teacher and students in front of a school building.
The Zapatistas live largely outside Mexican government rule in their own democratic formations called caracoles. Photo: Schools for Chiapas.

 

Free and open-source software movements put into practice much of the Commons' values. Combining this approach to software development with cooperative, community-based economic models can help us build technology that is sustainable and helps facilitate and defend the commons.  

The Tech Industry's Role in the Commons Transition

As mentioned, the commons is all around us. Yet these commons are constantly battling enclosure, and many more commons projects need our support to take hold. The first step is to take stock of the commons we are currently part of. Millions of us are already members of credit unions, food cooperatives, worker-owners in cooperatives, purchasers of cooperatively produced goods and visitors to cooperatively managed parks and open spaces.

This morning, I walked to the Westwood Food Cooperative to buy produce and am now typing this essay at Kahlo's, a Mexican-American family-run restaurant with a plant-heavy menu. I am a worker-owner of Agaric, a tech cooperative. We're also members of MayFirst, a cooperative itself which provides the hosting infrastructure for our clients. The commons are everywhere.

How might we better support the commons we are already part of?

The best way to find is to ask. To find commons near you, visit SolidarityEconomy.us. It's not comprehensive, but it's a good start.

Once better connected to the commons you are part of, examine what other aspects of your life can align with the commons. If you tend to shop at a big box store, look into local food co-ops and community supported agriculture (CSA). If you work for an agency, consider how you might transition it to a cooperative with a social-mission prioritizing sustainable practices. If you don't see your company moving in a democratic direction, you can still shift it that way by unionizing. These are tall orders, but then again, these times call for tall orders.

Lead By Example, But Towards Systemic Change

The quickest way to effect change is to work within our spheres of influence. But one person shopping at a food co-op instead of Wal-Mart is just a drop in the bucket. How do we make our individual actions add up to the systemic change we need? In the essay "We Can't Do It Ourselves,"
published in Low Tech Magazine, Kris De Decker explains,

A sustainability policy that focuses on systemic issues reframes the question from “how do we change individuals’ behaviours so that they are more sustainable?” to “how do we change the way society works?”.  

De Decker elaborates that,

Addressing the sociotechnical underpinnings of “behaviour” involves attempting to create new infrastructures and institutions that facilitate sustainable lifestyles, attempting to shift cultural conventions that underpin different activities, and attempting to encourage new competences that are required to perform new ways of doing things.  

Low Tech Magazine is leading by example by running their website completely off of solar power they themselves produce. I encourage fellow designers and developers to check out the site and the detailed write up on the meticulous, thorough work they did to minimize the site's energy usage and rig up solar panels to power the server the site runs on.

Screenshot of the low tech magazine website.
Low tech magazine puts their principles into practice by running their website on solar power.

 

Similarly, however we can, as tech workers we should be building our technology sustainably and in service of regenerative relations.

Use and Demand Renewable Energy

We must move away from fossil fuels and towards clean, renewable energy. For Agaric, this means getting the hosting providers we partner with to use clean, renewable energy. Most of our sites run on MayFirst, a tech cooperative we are members and leaders within. I started a discussion thread to transition our tech stack to clean, renewable sources . The discussion has become an initiative. Our work is just getting started, but this shows the benefit of meeting our needs democratically.   

You can see where your hosting providers stand by using https://ecograder.com

If your host isn't on 100% renewables, talk to them and work to get them there.

You can also choose to go with a hosting provider that's already green, such as https://greenhost.net

Design for Energy Efficiency

Web development trends have lead to massive growth in the size and resource usage of websites. There are counter trends appearing in response - static site generators, lean content strategies and sustainable design. Just as we care about the energy efficiency of our cars, homes and appliances we should care too about the carbon footprint of our websites and apps. Plus, simpler, efficient online tools facilitate easier maintenance and faster load times for users (especially important for those on limited data plans and older devices). As contributors and proponents of Drupal, there is certainly room for improvement within our practice for more sustainable design.

Divest, Invest for the Transition

Technology is not neutral. What it is put into service of has tremendous impact. The climate strike demands of the Tech Workers Coalition are a great starting point.

  •  Zero carbon emissions by 2030
  •  Zero contracts with fossil fuel companies
  •  Zero funding of climate denial lobbying or other efforts
  •  Zero harm to climate refugees and frontline communities

Work to formalize these principles at your own workplace and make them public. If you have contracts with fossil fuel companies or climate deniers work to end them. A great group to link up with around this is ClimateAction.tech

Unionize to Build Counter Power

Logo of the Campaign to Organize Digital Employees
The Communication Workers of America have begun organizing workers in the tech and game industry.

 

Not all of us work in democratic workplaces. For most of us, creating change in hierarchical startups and corporations is more difficult. Most companies are oriented towards shareholder needs, not worker or planet needs. Unions build counter power, forcing business to take our needs into account.

This is a daunting task. However, worker self-organizing is on the rise, especially in our industry. What starts as an internal petition signed and sent to management, can build to lasting formations that can shift companies to align with the values we need to make the transition.

Joining the Campaign to Organize Digital Employees is a great way to get started.

Conclusion

Transitions aren't easy. They're uncomfortable, they require risk and there's no guarantee of success. Still, fixing our sights on a world of care, balance and right relation with the earth and then making it so, in our home and in our workplace is deeply rewarding.

Industry audit and competitive review

You may in many ways be without peer, but there are always competitors for the attention of your audience. Identifying top peers and reviewing their respective content helps you get a wider perspective both on what potential listeners, members, and donors will be seeing and what seems to be working for others— we can start thinking together about where to emulate and where to differentiate, informing all of our work together.

Content strategy

Building on the review of peers, Agaric will work with you to briefly interview current and potential clients and develop personas and user stories.

Content style guide

Along with bringing consistency to cooperative output (and saving time sweating the details every time they come up), a good content (copywriting) style guide incorporates suggestions for clear and effective writing and helps your unique aspects shine through. It can help tell your story in a consistent way and help let your individual personalities show through while maintaining collective coherence.

User research and testing

Agaric applies a Lean UX Research methodology to answer critical user experience questions with relevant, meaningful, and actionable data.

From reviewing your goals and audiences we recommend answering the following questions:

  • What prevents users from becoming paying subscribers or sustaining donor members on the site?
  • What features would enable users to invite friends to become supporters?
  • Who is most engaged? least engaged?
  • Which conversion goals are being met? unmet?
  • What new audience do we want to reach?

We recommend and use the following research and testing approaches:

  • A/B testing
  • Brand audit
  • Browser and device analysis
  • Competitive analysis
  • Content audit
  • Contextual inquiry
  • Heat map analysis
  • Heuristic evaluation
  • Site analytics review
  • SWOT (Strengths, Weaknesses, Opportunities, Threats) analysis
  • Usability testing
  • User interviews
  • User surveys

Not all will fit the purpose or budget of every part of a project, but good insights into what to build and why is more valuable than simply building well and quickly.

User testing & revisions

We always recommend at least one round dedicated to measuring and improving. Using analytics and user tests, we identify what is working, what is not and needs to be changed, and what is missing and needs to be built. We then build on the previous work to do the fixes and enhancements with the highest expected impact.

People contributing modules or themes for listing on Drupal.org receive a welcome, or lack thereof, that would have driven away many of us now active in the community. With hundreds of requests moldering awaiting review, the project application process continues to be a community crisis, and it has been acknowledged as such for five years. We are casting aside the literal future of Drupal, with a likely disproportionate impact on disadvantaged contributors. Any separate process for new contributors will inherently be unequal, and will tend toward awful. Let's jump in to mitigate the damage being done and finally get a new system in place— we're closer than ever.

After a couple frustrated module makers asked me to give their projects full status, I went over to the project application review queue out of the sense that it isn't fair to everyone else to save only the two who reach out. Of course, I should have been in there all along: there were project applications which had been vetted by other volunteers and marked Reviewed & Tested by the Community four months ago. One person who contacted me was unhappy their project had passed all the hurdles and was then left lying untouched for a mere two weeks. Of course, they had started the application process nine months ago.

New project applications marked reviewed and tested by the community

The door through which community members can make their first contribution of a module or theme remains locked, and not enough people have the key (nor is it clear how to get that key to more people).

Keep in mind this is only projects that have actually been reviewed. In nearly every case the person applying has fixed the issues noted and now the project has been considered by someone to be all set for approval. People trying to get to that point are even worse off. The current backlog for people waiting to get a review has projects waiting with the needs review status for nearly a year — 11 months and five days. And of course the current project application review process, despite having gone through several iterations of improvement, still garners its share of complaints when running perfectly— and it still holds new contributors to a higher standard than we hold ourselves.

Finally, some unknown but large percentage of the two thousand projects marked "Closed (won't fix)" have been put in that state automatically by a robot due to lack of activity. If a contributor leaves an application in a "Needs work" state for a month, it is unceremoniously closed without warning. (In contrast, if we don't get around to reviewing or approving a project for months, nothing automatically happens in favor of the contributor, despite written guidelines for escalating ignored issues.) It will be fun to go through all these old issues and contact the contributors letting them know they can promote their sandboxes to full project (and then changing the issue to some other status, like works as designed, to mark it), but we can't do that until the overall process is fixed. The good news is we're closer than ever.

The current proposal looks solid, but it's suffering from inaction. The goals it outlines are excellent:

  • We need to remove the gate to new contribution entirely - not just kick the can to a particular elevated role, or a specific limit on the # or kind of releases a new contributor is allowed.
  • We need to continue to send strong signals about security coverage to users evaluating whether to use modules from Drupal.org.
  • Follow-up: We need to find ways to preserve the value collaborative code review, through changes to Project Discovery to provide signals about code quality, and by providing incentives and credit for review.

I encourage anyone who cares about new people joining Drupal to work on the issues associated with this proposal, in particular the ones to allow non-git vetted users to promote sandbox projects to full project status and add a permission for creating stable releases, and grant to “git vetted” users. While my oft-stated preference is that any gates we put up must apply to all users, so we make sure they are bearable and don't forget about problems for months and years at a a time, moving the gate to a security review at a stable release has huge advantages of its own. It allows a new contributor to put their work out there without being blocked by anything. It allows a module to find its audience and have people invested in its particular functionality at the point of review, rather than have only volunteers who have no inherent stake in the functionality involved. It even lets a contributor decide whether a module has proven sufficiently useful to others to be worth going through security review.

We don't have that system yet though and we still have that huge backlog to get through. Helping other people follow the project application checklist is a great way to get better at making projects yourself— whether you have a dozen already, or don't have any yet. Just remember this is about helping applicants. To give further incentive to the review work, i've proposed including issue credits given to users in the Project Application review queue on profile pages and Marketplace rankings.

It's Rosh Hashanah, the Jewish new year, and the tradition is that we have ten days to make things right with any people we have wronged. Let's accept (again) that we as a community have wronged our potential new contributors, and make things right. Thanks.

Join us on Agaric's Meet.coop BigBlueButton videochat & screenshare for presentation and discussion, February 2, Sunday, at 15:00 UTC (10am Eastern).

https://meet.agaric.coop/rooms/a8m-x61-skh-ift/join

How can a group of thousands of people talk about and decide anything? How's this 'community' concept supposed to work at scale, even in theory?

Any Free/Libre Open Source Software project will have elements of do-ocracy (rule of those who do the work), but not all decisions should devolve to implementors. A better ideal is that decisions should be made by the people who are most affected.

Particularly when a decision strongly impacts more than those who carry it out, we need better ways of making decisions that give everyone their say. This starts by letting people by heard by everyone else. Fortunately, we can scale conversations and decisions in a fair and truly democratic way.

 

Image credit: "Anti-Muslim Ban Protests" by Mrs. Gemstone is licensed under CC BY-SA 2.0.

Stay in touch

Drutopia Features

Actions

An action is a call for concrete work from supporters. It can stand on its own or be part of a campaign. It can have a goal and due date set. For example, a call for 50 people to call a prison by June 13th demanding an investigation into prisoner abuse. An action can also be turned into a fundraiser, allowing people to donate directly to the site through Stripe. No longer will groups be dependent on proprietary platforms such as GoFundMe and IndieGoGo.

Articles

Drutopia provides an article content type and related configuration, including article types (such as "Victories" or "Press releases") and topics which span all kinds of content on the site (such as "Tenant organizing" or "Environmental racism").

Blog Posts

Drutopia provides the blog content type and related configuration, ideal for giving individuals or groups more informal voices distinct from the organization as a whole.

Campaigns

A campaign page is a central place to explain an issue, publish updates about its activity, list out demands, post calls to action, and raise funds.

Groups

  • Groups broadcast to supporters their activity and ways to support.
  • Each group has a page within the website. A group can launch a campaign, call for an action and publish a news article.
  • All of these pieces of content are displayed on a group's page, creating a mini-site.

Profile Pages

Drutopia provides a People content type for showing visitors information about staff, volunteers, contributors, and more.

The Drutopia Initiative

The Drutopia initiative lays out a technique for configuring a Drupal distribution, for the commons.  It is a recognition and a reflection in software architecture that liberation requires organizing and collective action. We ask you not to sit back and let Drutopia work its magic, but rather to stand up and, with us, build a cooperative of grassroots organizations that work together to build tools that we can own together.

Core values of the Drutopia initiative:

  • Be inclusive regarding gender, gender identity, sexual orientation, ethnicity, ability, age, religion, geography, and class.
  • Commit to protection of personal information and privacy and freedom from surveillance
  • Value collaboration and cooperation above competition
  • Prioritize human needs over private profit
  • Foster non-hierarchical structures and collective decision-making

Drutopia encourages:

  • Users and adopters to pool their resources and take a lead role in prioritizing and crowdfunding new development
  • Designers, site builders, and developers to focus on rolling their work into shared solutions available to everyone, heightening the ability of groups of all stripes and sizes to benefit.

Strategy - Shared Configuration Management

Drutopia focuses on a specific use case for websites — grass-roots organizing — and pioneers an elegant model for reducing the costs of maintaining an individual Drupal site by providing a shared base configuration for a collection of websites that are run by various organizations with similar needs that contribute to the development cooperatively.

Learn more specifics about the cooperative development strategy behind Drutopia by reading the Drutopia White Paper.

Drutopia as a LibreSaaS or Platform Cooperative

We believe that the platforms that influence and affect so much of our lives (think Facebook and Google) should be owned by the people who use them. In the same line of thinking, the potential of the Drutopia configuration framework is truly unleashed as fully hosted, member-owned platforms. Members of the platform cooperatives will drive forward the vision of the project from the perspective of those most affected– shaping the development of new features. The platforms themselves can span multiple participating hosts that endorse and follow the hosted Drutopia standards.

Contribute to the Drutopia Initiative

Drutopia is a fully functional content management system apart from all these goals, and there are a few ways different individuals and organizations can contribute to this initiative:

1) Drutopia as a Drupal distribution that can be self-hosted by anyone, but the software project will be democratically governed by members of the Drutopia cooperative. For as little as $10 a year you can become a member who votes in leadership team elections, suggests features for the development roadmap, and is part of a community that is building tools for the grassroots.

2) Non-profits and other organizations that pay Chocolate Lilly or Agaric to build a Drutopia website for their organizing will be contributing to our development efforts, and helping us to move forward in attaining the goals of the Drutopia initiative.

3) Individuals and groups that recognize needs for specialized Drupal distributions should talk to us. We encourage you to reach out and bring together others that share the same needs, so that we can collectivize the development and maintenance of more Drutopia distributions. 

Cooperative Webhosting

Staying true to the core values of Drutopia, we hosting your site through, and include membership in, democratically governed May First Movement Technology cooperative.  May First is dedicated to supporting organizers and activists by providing tools and services that protect their data and privacy from governments and corporations.

Updated 2025 for changes in Drupal 9 and Drupal 10; now valid for Drupal 10 and 11.  Key changes are noted below.  (If you need the old Drupal 8 instructions, we can send you the old copy— or probably better, hire us to upgrade.)

While creating content, there are pieces of information that are only relevant when other fields have a certain value. For example, if we want to allow the user to upload either an image or a video, but not both, you can have another field for the user to select which type of media they want to upload. In these scenarios, the Javascript States API for Drupal can be used to conditionally hide and show the input elements for image and video conditionally.

Note: Do not confuse the Javascript States API (powered by FormHelper::processStates) with the storage State API.

The basics: conditional fields in node forms

Let’s see how to accomplish the conditional fields behavior in a node form before explaining the implementations for paragraphs. For this example, let’s assume a content type has a machine name of article with three fields: field_image, field_video, and field_media_type. The field_image_or_video field is of type List (text) with the following values: Image and Video.

/**
 * Implements hook_form_alter().
 */
function nicaragua_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_article_form' || $form_id == 'node_article_edit_form') {
    $form['field_image']['#states'] = [
      'visible' => [
        ':input[name="field_image_or_video"]' => ['value' => 'Image'],
      ],
    ];

    $form['field_video']['#states'] = [
      'visible' => [
        ':input[name="field_image_or_video"]' => ['value' => 'Video'],
      ],
    ];
  }
}

Conditional field syntax is so squirrelly if you have access to equivalent fields directly on a node form, or want to create them temporarily, test your `#states` there first.  For example, boolean fields as the controlling field now look like this:

  $form['field_dependent']['#states'] = [
    'visible' => [
      ':input[name="field_controller[value]"]' => ['checked' => TRUE],
    ],
  ];

Note the [value] in the name.  You can see this in your browser's inspector, and that is the best way to figure out what to target.  Other special fields may also have extra parts beyond the field's machine name, the field name of a field type provided by Colorfield, for example, looks like this: "field_background_color[0][color]".

In modern Drupal, the node add and edit form have different form ids. Hence, we check for either one before applying the field states.  (An alternative would be to implement hook_form_BASE_FORM_ID_alter for the base of both kinds of node forms, `node_form`.)  After checking for the right forms to alter, we implement the fields’ states logic as such:

$form[TARGET_FIELD_NAME]['#states'] = [
  TARGET_FIELD_STATE => [
    CONTROLLING_FIELD_SELECTOR => ['value' => CONTROLLING_FIELD_STATE],
  ],
];

CONTROLLING_FIELD_SELECTOR is a CSS selector to the HTML form element rendered in the browser. Not to be confused with a nested Drupal form structure.

Conditional fields in Drupal paragraphs

Although hook_form_alter could be used in paragraphs as well, their deep nesting nature makes it super complicated. Instead, we can use hook_field_widget_single_element_form_alter to alter the paragraph widget before it is added to the form. In fact, we are going to use the widget specific hook_field_widget_single_element_WIDGET_TYPE_form_alter to affect paragraphs only.  (These hooks replace `hook_field_widget_form_alter` and `hook_field_widget_WIDGET_TYPE_form_alter` respectively; see the "Streamline field widget hooks" change record.)

For this example, let’s assume a content type has a machine name of campaign with an entity reference field whose machine name is field_sections. The paragraph where we want to apply the conditional logic has a machine name of embedded_image_or_video with the following fields: field_image, field_video, and field_image_or_video. The field_image_or_video field is of type List (text) with the following values: Image and Video.

Note: The WIDGET_TYPE is replaced with `paragraphs` when you are using the newer Paragraphs widget but `entity_reference_paragraphs` if using Paragraphs Classic; add `_browser` to those names if using one of the respective widgets provided by the Paragraphs Browser module; you can get these IDs by looking in the src/Plugin/Field/FieldWidget directory of the relevant module.

/**
 * Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter().
 */
function nicaragua_field_widget_single_element_paragraphs_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
  /** @var \Drupal\field\Entity\FieldConfig $field_definition */
  $field_definition = $context['items']->getFieldDefinition();
  $paragraph_entity_reference_field_name = $field_definition->getName();

  if ($paragraph_entity_reference_field_name == 'field_sections') {
    /** @see \Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget::formElement() */
    $widget_state = \Drupal\Core\Field\WidgetBase::getWidgetState($element['#field_parents'], $paragraph_entity_reference_field_name, $form_state);

    /** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */
    $paragraph_instance = $widget_state['paragraphs'][$element['#delta']]['entity'];
    $paragraph_type = $paragraph_instance->bundle();

    // Determine which paragraph type is being embedded.
    if ($paragraph_type == 'embedded_image_or_video') {
      $controlling_field_name = 'field_image_or_video';
      $selector = sprintf('select[name="%s[%d][subform][%s]"]', $paragraph_entity_reference_field_name, $element['#delta'], $controlling_field_name);

      // Dependent fields.
      $element['subform']['field_image']['#states'] = [
        'visible' => [
          $selector => ['value' => 'Image'],
       ],
      ];

      $element['subform']['field_video']['#states'] = [
        'visible' => [
          $selector => ['value' => 'Video'],
        ],
      ];
    }
  }
}

Paragraphs can be referenced from multiple fields. If you want to limit the conditional behavior you can check the name of the field embedding the paragraph using:

$field_definition = $context['items']->getFieldDefinition();
$paragraph_entity_reference_field_name = $field_definition->getName();

If you need more information on the field or entity where the paragraph is being embedded, the field definition (instance of FieldConfig) provides some useful methods:

$field_definition->getName(); // Returns the field_name property. Example: 'field_sections'.
$field_definition->getType(); // Returns the field_type property. Example: 'entity_reference_revisions'.
$field_definition->getTargetEntityTypeId(); // Returns the entity_type property. Example: 'node'.
$field_definition->getTargetBundle(); // Returns the bundle property. Example: 'campaign'.

In modern Drupal it is a common practice to use the paragraph module to replace the body field. When doing so, a single field allows many different paragraph types. In that scenario, it is possible that different paragraph types have fields with the same name. You can add a check to apply the conditional logic only when one specific paragraph type is being embedded.

$widget_state = \Drupal\Core\Field\WidgetBase::getWidgetState($element['#field_parents'], $paragraph_entity_reference_field_name, $form_state);
$paragraph_instance = $widget_state['paragraphs'][$element['#delta']]['entity'];
$paragraph_type = $paragraph_instance->bundle();

The last step is to add the Javascript states API logic. There are two important things to consider:

  • The paragraph widgets are added under a subform key.
  • Because multiple paragraphs can be referenced from the same field, we need to consider the order (i.e. the paragraph delta). This is reflected in the CONTROLLING_FIELD_SELECTOR.
$element['subform'][DEPENDENT_FIELD_NAME]['#states'] = [
  DEPENDENT_FIELD_STATE => [
    CONTROLLING_FIELD_SELECTOR => ['value' => CONTROLLING_FIELD_VALUE],
  ],
];

When adding the widget, the form API will generate markup similar to this:

<select data-drupal-selector="edit-field-sections-0-subform-field-image-or-video"
  id="edit-field-sections-0-subform-field-image-or-video--vtQ4eJfmH7k"
  name="field_sections[0][subform][field_image_or_video]"
  class="form-select required"
  required="required"
  aria-required="true">
    <option value="Image" selected="selected">Image</option>
    <option value="Video">Video

So we need a selector like select[name="field_sections[0][subform][field_image_or_video]"] which can be generated using:

$selector = sprintf('select[name="%s[%d][subform][%s]"]', $paragraph_field_name, $element['#delta'], $controlling_field_name);

By using $element['#delta'] we ensure to apply the conditional field logic to the proper instance of the paragraph. This works when a field allows multiple paragraphs, including multiple instances of the same paragraph type.

You can get the example code here.

Bonus:  If you want to show or hide a field inside a paragraph form based on a field on the node form itself, go right ahead— the controlling field selector code will be the same as it would be for a dependent field on the node form itself, for example ':input[name="field_controller[value]"]'— no need for the complex subform selector needed when the controlling field is also in the paragraph form.

Warning: Javascript behavior does not affect user input

It is very important to note that the form elements are hidden and shown via javascript. This does not affect user input. If, for example, a user selects image and uploads one then changes the selection to video and sets one then both the image and video will be stored. Switching the selection from image to video and vice versa does not remove what the user had previous uploaded or set. Once the node is saved, if there are values for the image and the video both will be saved. One way to work around this when rendering the node is to toggle field visibility in the node Twig template. In Mauricio's session "Twig Recipes: Making Drupal 8 Render the Markup You Want" there is an example on how to do this. Check out the slide deck and the video recording for reference.

What do you think of this approach to add conditional field logic to paragraphs? Let us know in the comments.

Sharing work between cooperatives.

Agaric hosts a weekly online gathering known as Show and Tell. Participants share tips and tricks we have learned and pose questions to other developers on tasks or projects we are working on. Each week we ask people to send us a little info on what they would like to present. This is not a prerequisite, just a suggestion. Having advance notice of presentations allows us to get the word out to others that may be interested, but you can just show up, and there will most likely be time to present for 5-10 minutes. Sign onto the Show and Tell mailing list and be notified of upcoming Show and Tell events.

Recently we have opened up the Show and Tell chat to bond with other cooperatives that do web development work. Agaric was contacted by members of Fiqus.coop in Argentina as they had started an initiative to meet other cooperative developers and share values and goals. No one had sent notice of a presentation, so we switched the topic of the chat to be more of a meet and greet to get to know each other better with the goal in mind to be able to share our work on projects. The value of the meeting was immediately apparent as we delved into conversation with a few members of Fiqus.

Next, we invited more developers to take part in the discussion, and the doors were opened to share more deeply and connect. This week our meeting was over the top! Nicolas Dimarco led us through a short presentation of slides that revealed a  Federated process and workflow to share development with members of multiple cooperatives. The plan is so simple that everyone immediately understood and the conversation that ensued was compelling, and the questions were indicative of where we need to educate each other about cooperative principles vs. corporate tactics. We need more discussion on trust and friendship. There are so many developers in corporate jobs that have asked me how a web development cooperative works and how does a project run without a manager. I first explain that projects do have managers, but they are managing the work, not the people. Taking time to get to know each other's skills and passions about programming is a core part of being able to work together in a Federation. Fiqus.coop has made it plain and simple for all to see the path to sharing work on projects!

Here is a link to the video recording of the chat where Nicolas Dimarco of Fiqus.coop presents the formula for federated work among cooperatives. Here is a link to the notes from the meeting on 3/20/2019 and some past Show and Tell meetings.

More information on Show and Tell.

Some Drupal shops already work together on projects and we can help that grow by sharing our experiences.  We would love to hear about the ways you work and the processes you have discovered that make sharing work on projects a success!