├── .gitignore
├── .travis.yml
├── LICENSE.md
├── README.md
└── html_generator
├── .gitignore
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── config.rb
├── scripts
├── generate-key-mac.sh
└── predeploy.sh
└── source
├── images
└── .gitkeep
├── javascripts
└── application.js.coffee
├── layouts
└── layout.erb
├── readme.html.haml
└── stylesheets
└── application.css.sass
/.gitignore:
--------------------------------------------------------------------------------
1 | # osx noise
2 | .DS_Store
3 | profile
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.0.0
4 | env:
5 | global:
6 | # See html_generator/scripts/generate-key-mac.sh
7 | - secure: "Po9JQCPGko0dWF1AaYYZlsbEpV3kgAh28821dBHRLDwl6vg7JTyTAvjTjEvbsqYTdfD6y0VbMARIKf+RTXy1azdlAm4yp8a8j6UX2IWuFJ6Om59y2TdPFpr7Qs8WR/G/CrivtxUbEHYfDPeIJFDo9BaEjpwe/ysmp4QsaAVMPxw="
8 | - secure: "fCnrHwRUXKDBGNAH4ODL4EJFEArfT798XAdY4Ltdp2gnXOtQnVVI+xZpKMfGE5txFhvTpujJvw4vsgaeAwck2pCJm1NY0tBoVix+dVoKAV/gs7tQGzheAF7jY5KfKzFaY6606rWbdxxo06W4Ka3XI0oqulqnnA5AL0WiUJWRc/Y="
9 | - secure: "mw9gPtxHFOwRteSJDo4kv0XkgbwAoGCjOQg90WMUOAuUhi2gpyo0B8lZkYAz1Duvq5zyQaJCX6eLIJatJmn7KPu9VrlwlMTufp5BPkRsAOzK9QGEuQHYuqnQL0Lh4zk2dol5GJcKXxzPi/BkqIH+bbe8B8pY+4ojLcC8h1xtMJA="
10 | - secure: "ozHDTfaq3N42U0qpQ+QJBpXHOyzKFMruOsB6F1PAvMnewl+gXkVwvrGzxyytcXdEEprC6+M93zxaHBT16wLrarRlZjMhmwOteL5Zeqsrbaa7DjdZnpLJ24SFnfe3d0PyWhHYQTuh1R6ThIFl7v65/QgbDuViktEqutyu3Wmt6lY="
11 | - secure: "DMsTLVi7sY1mroFKfHaiZX+fbkDK3PBdZlxr+RYQQZUNegrsP3ff7zyLdfKIqRFLegZvNQZ0qwlWqhT6wujAkKOf9o69mAYJ2Aq/6DSK8gA18rWNs6Ppb0pmR4Ta+d/VT3k4PaZbbPrLmMhQFWWsodtjIiM9NtsqazAiIXE5SSU="
12 | - secure: "vfuXrmMPmZJ3UlX8olgf5XMtt6HmnzcL6HHU7Spn/kZe1v8Ox+B6/evhtQ8/Gsydh0K+W4zOiMaH9LVhHXFZ6Yflw+nTrRLaHYdY1MJdJAS7WvfVPatrnCc8KdZQSawUW5Fr91QbT6Ho2aJiF0CJ4fKhRmfULq7LiEeQ+N5DaV4="
13 | - secure: "alezYiM7PC0mvWtUgZRRlTbBMUp518cTAjXYKJ3GvlcoiAXA7Av0jX4fG2jxQ7Gzwo7ReCXR018RRaK4dAdy9o1nuoG0eI6LRCdBQWdTGI/29Y2nsr3THToOiSIIEJNyzHXhlFGKKJ7V/P0zbxRqgwO6sRIARyAHb5tRotoZkLQ="
14 | - secure: "lpU3oZQtT/bMwxE9r8L6kmZstFWa3s71woQTDp+AfVAQ76DEPz9mKARvd6aCWgFN8ZFW00hzSIEHJVkjYBBTld9Spvgi7jkgpbym/jRRyITOfKpl1X5gxq04abrpZuM579JrfUc8tSyF94KdL1tgHl0L4NBLzuNby1oyERO+JwU="
15 | - secure: "zPjPWBjtpiTsHePeYZHNU0Svl8DVotCsl61GW5wl7gTSEsm8KANMwOcGxjTyYWy8rMVpQOnDY0JUP8E56GIrX9xFu59xJTO/PL/e/DcvRa1DFDRjGwEaCPSOe9UVpWvMIYNeMvCueasBpQsaHNmJLu/j8quADbI/0U0J1XWq3AI="
16 | - secure: "eCclHoQqw5x1GwCeNMsFw+KPR3BQli/P1fbVIAPBmfXi0LoZwIJi/df6Lgrc76BRHfDVSeORYapE/X1JCSWUk4YNT4gmrZ5T/Q226EMH7SQKWwrrj/ABcky/OzWB90zqp/Ky+FY8exWSo3aiEgnu3n5RZIKtw0MImUUOdJGGFcw="
17 | - secure: "dRasnrwCtXZCAkKr9KHGdWNfYSXRM3MD+2cAqH2x3xnQ+7Ko6p8fJAN6zAI1hNkObiC1nBoPKo271vj0VOpYzUT/6wpF+F1T3SJj/xUPu7yXDXgoSqWhI1nCEv/Lbi/E4uKuVE7jTLjVtJHjlayYPZf2bHwHDdyb8Zp4/jFE53E="
18 | - secure: "dLolWbX3nmQ+0IIqJQMZBd0PP38+/X96zxXv7qkij9uFfDVMVR9vsc9z8nJBmQt9Roa5vZzsf6reWkIJbo9SyzdbeCixWSOW64xhM2PBzUuOu/t67iur1WxpN3SBYUUVG8Hxrz9YSKdX9KAV8cQgbUPz3HPwqoAXGXtPatwBzfY="
19 | - secure: "OnVpKqz3Cet6PcdQZutGSC37MATOfEwUo/mWhno9Lm7gplUklRjkF9/KJdGhDlqjIZk9/UWoFOkbU/owFYmVnT7/rHRfjdgh0EeneZAT3taHq42n7/FRK+2AT3iV+ktW/GAYcOqU85/LnUA/GSJ8F16iGjiqmFDYYtOuaf1c/DM="
20 | - secure: "RJHBOX21raN2ZM5QNtaQvIuxPRUNpauXupMCyL6MlO6UNVFAZGw1TBpAak/cf7siF8F+LGXSva6+GXnBexSCitmnnHtJVV+Fq6afNvNTIqRx0BT8a/fsV51PEPZpbjKey2RoJFWEgS6FrsjPQjX6/7ZJsT4U7dJkF5FpaDV9a1E="
21 | - secure: "D2cChy4jNSYqQqmDCVBDUbRw6Ccibw1F+erIFHx0FUJGO5GJttaYXiHnX27MDRviycqzoALiOgsgUz4Y9S0/dupxAGJ42ZubBN02GkbgShnNWQ2EYWwWqJ/7RxcTcKQnQBQVzXCc07bpJjXUOW0tKUwhp4r46xpDGKM45nHFO4A="
22 | - secure: "l5jgBZiljRmwHJbyi2wODpSSYowYOIPhSAB0mosutYv+RRXa6E+PE0S5csgSQKkt7DgnmO2zB88Lo2Cp/vomQUtsFfD3V6B0Y4GhbxOxRTByL1ljq/cwNpw0n6ehMpoFO3bOloVI1xC1fmlO6q5Wucg4OgtTp7Viz4uyNlripzQ="
23 | - secure: "gr2QWY0LjXYqTE0fp5Vqw45HezRCJvyMz2zsoCHJbopuXIdTHNTGRT2I3b7ykl3xCSdEusmUhBxx3+wU015d2hBnh2rOqQJKIhvEoJoV9JIblPlqEUXqqmJswh/sjrtVogfgJSBp/diDqrcHtg24s+XLpyR51kEKLEnv/bW67NQ="
24 | - secure: "t+dsj9/SziEKmBC/KlGoHV8Dn5iQDMAoWRFJk5eUG5cvQdDoN/cuc5a101f5doinUwj2FOfhE6g4AOCM3r8pnKmXEtneuPccUCQ+7tuOIEQae+snPlObCr+oDZEnSHaaT+6iwA2ToTp8bdDdleZptGiogzC8uBFsZWKHZe9k3V0="
25 | - secure: "lY30kB7WgyoRnPoItzbjpUaWPL0+KphEfU7j/VYcNIp818cfeTBfkDanc5PZSuqsBhA4IIB0glSdXESEfq9fueXEtP3CxqQexmy3LMpyEOcHkcfdUhqvNIw5wEY0bGLyNjTfSdib5kfETS/OMlv8OMiYhvGgo+nwnDftb/Ec7vY="
26 | - secure: "cj7DMBUuzKjflfsajB5+GbqCFCq2qCxFKvArajOwdP9I0+K6jA1IjBoUC4IF3waZaGyGaPFNfdWvAcrHwQMjyVIitJAKfFNqtUydA4xFgO4SdnUwdYe/y6r4tKQ9NwnJxGg9JFmVC8vyM/XC01RzbIOSLaOR42psix28lU46kYw="
27 | - secure: "xLjf0sQrH3popFeZ7p0IU04TkR+wBoEps2xIIDG+sy899Y3qREpKKILwxtykw2u8/zYDeNfsM8GEXHEuJFJOK5LR/q7LhpdZD8WQM2DxQTzL07x3IYad9dGVe5iRjThgOdGRJIdCsrRnwenBvTQzVQ2ScBQKwfk2U0HlERdyj/E="
28 | - secure: "2zRVL6xFYH1jbksMDKu6Hjd1Rl5B+nY63asYkASb5lvEeWVp+bzeNWTevO6b2k7U9Wxt7epGuAr3Zwli99hwu4pnJ6v22q1xcBJFNc74PDOD1KmgeC5anYFtvrGlXNLkOB4GxmzTJEzsc0MJ8nd0qm/hRt/G81+VDCqtnqiuoOs="
29 | - secure: "cp7haAIavMegt4caNqa6caXnhypQK/k8yz1Ztuvqzs/2bHa2+rdB2+U2urVHdXlTn1L0zXTMTblG50I8Lxroh2GaJtIQzzQ0B2PSrJAvPAWt7tHu4ewx6nVyt8IO2VosuD0P9Lh8JhEIv14hQgPr2F4bK/yGyQ16vYCkPs3UzM0="
30 | install:
31 | - cd html_generator
32 | - bundle install --deployment --path=${BUNDLE_PATH:-vendor/bundle}
33 | script: bundle exec middleman build
34 | after_success:
35 | - if [[ "$TRAVIS_BRANCH" = "master" ]]; then rm -rf build; ./scripts/predeploy.sh; rake publish ALLOW_DIRTY=true; fi
36 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013, Code for America All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 |
5 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
7 | Neither the name of Code for America nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Civic Tech Patterns
2 | ==================
3 |
4 | In the spirit of [Wikipatterns](http://www.wikipatterns.com/display/wikipatterns/Wikipatterns), this is a collection of [patterns and anti-patterns](http://en.wikipedia.org/wiki/Pattern_language) for describing common practices that may help or hinder the conception or design of your civic technology.
5 |
6 | 1. [Design Patterns](#designPatterns)
7 | 2. [Idea Patterns](#ideaPatterns)
8 | 3. [Design Anti-Patterns](#designAntiPatterns)
9 | 4. [Idea Anti-Patterns](#ideaAntiPatterns)
10 | 5. [Types of Civic Applications](#typesOfCivicApps)
11 |
12 | ### Usage and Contributions
13 |
14 | To discuss any of these, please [open an issue](https://github.com/codeforamerica/civic-tech-patterns/issues), or fork and submit a pull-request.
15 |
16 |
17 | ## Design Patterns
18 |
19 |
20 | ### Civic Wayfinding
21 | Focus on clearly/accessibly explaining a process and offering a clear "now what" action step. Show people where to put their logical or emotional response: write their reps, letter to the editor, send story to local blog, etc. Instead of trying bulldoze through the walls of bureaucracy, hold people's hand in going up, over, or around them. Take them on a bear hunt:
22 |
23 | > We're going on a bear hunt,
24 | > We're gonna catch a big one,
25 | > What a beautiful day,
26 | > We're not scared.
27 | > Oh oh!
28 | > A river,
29 | > A deep, cold river.
30 | > We can't go over it,
31 | > We can't go under it,
32 | > We've gotta go through it!
33 | > Splish splosh, splish splosh.
34 |
35 | * Examples: [OpenCounter](https://github.com/codeforamerica/opencounter), [CPS Tiers](http://cpstiers.opencityapps.org/about.html)
36 |
37 | ### Go to the People
38 |
39 | Engage with people in the places they already go online: Facebook (**FACEBOOK!**), community blogs/forums or existing services (Foursquare, Twitter, etc.) rather than trying to get them to transfer their activities to your new platform. This could include: Facebook or blog widgets; bookmarklets or browser extensions; embeddable content; or messaging services (Twitter, instant messenger, etc.). This can work hand in hand with the *It Alerts You* pattern.
40 |
41 | ### It Alerts You
42 |
43 | Actively reach out to people when an action has taken place or further action is needed; don't expect them to frequently visit your website or open your application. Optimize your email messages for openings/click-throughs or utilize other messaging services (heck, even the postal service!).
44 |
45 | * Examples: [CivicsGarden](civicsgarden.herokuapp.com) tweets at you when your plant needs watering or has died.
46 |
47 | ### For Official Adoption
48 | Design your app to be officially adopted or replace an existing resource. You may need to invest more time in social processes (explaining, building trust, gaining buy-in) than engineering; or engineering may need to be focused on maintainance/infrastructure constraints or accessibility ([508 compliance](http://en.wikipedia.org/wiki/Section_508_Amendment_to_the_Rehabilitation_Act_of_1973)!) over raw functionality.
49 | * Example: [SR Tracker](https://github.com/codeforamerica/srtracker)
50 |
51 | ## Idea Patterns
52 |
53 |
54 | ### Reimagine
55 | Engage people in creative, curious or inane thought. Be unlike the "typical" experience or style of engagement with a topic or problem. One potential danger to this pattern is the lack of a clear action step.
56 |
57 | * Examples: [Blockee](http://blockee.org/), [JFDICitizen](http://codeforamerica.github.com/jfdicitizen/)
58 |
59 | ### Do your research
60 | Research common questions or phrases that people are googling within a topic/issue-area. Look at the top resulting links and build an app that is both subjectively better than the competition *and* has a chance of having a higher Google ranking. Google even has a [keyword research tool](https://adwords.google.com/select/KeywordToolExternal).
61 |
62 | ### Self-tested
63 | Build an application that you yourself fully and/or regularly use. Assuming you aren't a sociopath, though admitting that you aren't representative of everyone or even many-one, building something that is insanely useful to you can result in something that is relevant to others. Unfortunately, it's often easy to fall into the subsequent anti-pattern,
64 |
65 | ### Seek Out Existing Communities
66 | Find an existing community (online, offline, geographical, affinity, etc.) to discover problems, pain points and potential interventions. You get an automatic userbase with a shared identity who--assuming you're a good listener---already understand the problem your technical intervention is trying to solve. Beware of potential Idea Anti-Patterns such as *Intention Over Practice*, *Management Problems* or *Niche Tools*.
67 |
68 | ### Digitize a Process
69 | Build a tool that makes an existing process easier, faster, better, stronger. Ask, "is someone already doing this, but on paper or by phone?" At the same time, be aware that simply digitizing a process can take valuable social interactions out of what seems like an inefficient process. (See also: *Seek Out Existing Communities*)
70 |
71 | ### Make it Mobile
72 | Take information in a closed format and make it available to people when and where they need it. Today, that often means on a smartphone (which people do have -- see *Go to the People*, above, and *...and it has SMS*, an anti-pattern)
73 |
74 | ### Relevance
75 | Is the app doing something that matters to people in the field? For example, is it tracking things that matter to the people who are tracking them? Are you only tracking stuff that only matters to management?
76 |
77 | ### Have A Business Model
78 | Even as a thought experiment, asking “who would pay money for this and how much?” can crystallize intent. It'll help you find your audience and your value.
79 |
80 | ### Bridging tech capacity
81 | Is it doing something that the people who should make it cannot do for time, money, skill reasons? Maybe they already have tech capacity to do 90% of stuff, but just need help getting data out of the system, etc.
82 |
83 | ### Content before Engineering
84 | Can you explain a process so that people really understand it well *before* you build the system to contain the process? Are you an expert in that process and have actually experienced it? See "It's For the little people"
85 |
86 | ### A Happening
87 | An impermanent experience can be more transformative than a permanent artifact. Build a brief or one-off experience that someone (or a group of people) can go through and be done without any future expectations or collateral. Just because computers are really good at storing stuff doesn't mean you have to capitulate to their silicon whims. May be a subset of the *Reimagine* pattern.
88 |
89 | ## Design _Anti_-Patterns
90 |
91 |
92 | Anti-patterns aren't inherently bad. The are often difficult to achieve because their success relies heavily on non-tech stuff like community outreach, content creation and community management. Or, they might just be easy to implement badly. Think twice about adopting one of these patterns.
93 |
94 | ### Civic CMS
95 | "I need a site that has a neighborhood community calendar and a social network and a blog and a map and..." The boringest interaction model ever. These sites often end up abandoned: blogs with no posts for months, empty calendars, and spam-filled comments. Before starting one, ask "Who's going to update it regularly?" and "Why will someone read it?" Instead, consider starting a Facebook page, mailing list, Google calendar, or Twitter feed -- see the *Go to the People* pattern, above.
96 |
97 | A civic CMS might just be what you need if you already have an active online community that wants to take another step. For example, if your neighbors already all read your blog for events, but you want to make it easy for them to add their own, a CMS could be the solution. Just be wary of trying to do it all at once.
98 |
99 | > “Liberty cannot be established without content, nor content without content moderation.”
100 | >
– de Tocqueville
101 |
102 | ### ..and it has SMS
103 | We all know SMS is code for *those people*. If your conception of the experience of poverty, economic or social marginalization is "doesn't own smartphone", your app isn't serving real needs or context.
104 |
105 | ### Remove humans from the process
106 | The anti-pattern of *Digitize a Process*, above. Sometimes, taking a process online [cuts efficiency](http://www.nytimes.com/2012/10/09/health/the-ups-and-downs-of-electronic-medical-records-the-digital-doctor.html?pagewanted=all) or removes valuable human communication from the mix. For example, in [Close to the Machine](http://www.worldcat.org/title/close-to-the-machine-technophilia-and-its-discontents-a-memoir/oclc/37277573), Ellen Ullman describes an electronic social services system that lead to less communication between service providers who once traded details with each other by phone.
107 |
108 | ### Games that aren't actually games
109 | Zynga-style "badge acquisition" isn't actually "fun” despite being a “game”, it's just addictive. And it usually isn't even addictive -- no one will want to earn badges for shoveling their sidewalk, unless it ties into a larger system that people are already using (see *Go to the People*, above.)
110 |
111 | ### "Imagine a million users…"
112 | No, imagine one user (hopefully you); what's the immediate benefit to user #2?
113 |
114 | ### They'll find it via Google / if we build it they will come
115 | Nope. They won’t.
116 |
117 | ### And then they will tell their friends
118 | Nope. They won’t do that either, especially if "they" never came in the first place (see "if we built it they will come").
119 |
120 | ## Idea _Anti_-Patterns
121 |
122 |
123 | ### Focus on the negative
124 | Crime maps, restaurant inspections, waste/fraud/abuse. While these may be useful applications, they are overrepresented in civic technology. Also, these applications often do little to challenge people's preconcieved notions, let alone educate them on the process, policies and politics that generated the underlying data in the first place.
125 |
126 | * Example: [Don'tEat.At](http://donteat.at/)
127 | * Further reading: [Crime and Data Leadership](http://www.island94.org/2011/09/crime-and-data-leadership/),
128 |
129 | ### Simplify the Complex
130 | This anti-pattern describes the boiling down of a complex, nuanced or difficult-to-understood process/dataset into a simplistic analysis or kneejerk action-step. Often combined with *Focus on the Negative*.
131 |
132 | * Example: (nearly) all crime maps ever.
133 |
134 | ### Correlation = Causation
135 | Just because you can show crime rates on the same map as all the liquor licenses in your city doesn't mean you should. Correlation doesn't equal causation, and unless you have a good story to tell along with your data visualization, don't lead people astray.
136 |
137 | ### Stuff on a map
138 | [Put a bird on it](http://www.youtube.com/watch?v=0XM3vWJmpfo) and call it a day. Ask, instead, "what value does a map give?" A list, chart, or just plain text might be much more useful for your readers.
139 |
140 | ### “It’s interesting” / Pseudo Investigative Journalism
141 | Publish with purpose. Don't simply move a public dataset online because it exists. Don't be that newspaper that [published the home addresses](http://www.nytimes.com/2013/01/07/nyregion/after-pinpointing-gun-owners-journal-news-is-a-target.html?pagewanted=all) of gun owners "just because." The exception is if you're doing it as an exercise in learning a technology, which is cool.
142 |
143 | ### The Dead End
144 | If it doesn’t have an action step, so what? In some cases, it's fine if a page is a dead-end. But you probably brought the user to the page for a reason.
145 |
146 | ### Niche tools
147 | From ReportingOn's [farewell blogpost](https://web.archive.org/web/20120310083320/http://www.pbs.org/idealab/2010/12/lessons-learned-from-reportingon363.html) about building highly specialized tools for journalists (and applicable to just about any domain, like civic tech):
148 |
149 | > Unless what you're building meets a _very_ journalism-specific need, you're probably grinding your gears to build something "for journalists" when they just need a great communication tool, independent of any particular niche or category of users.
150 |
151 | ### Management Problems
152 | Ok, so you now you have a great user roles, permissions and auditing system; how does that make it easier for the people actually accessing and entering data into the system?
153 |
154 | ### No competition scan
155 | Make sure you know what's already been done. Where do you fit? Where can you add value? Are the existing sites good enough? There are plenty of untapped opportunities -- it might be better to start there. Then again, you do want to *Seek Out Existing Communities*.
156 |
157 | ### Intention over Practice
158 | You might be tempted to build something that people _want_ to do (or feel like they _should_ do), but ultimately don't.
159 | * Examples: The post-conference social network that seems like a great idea _at_ the conference, but subsequently goes unused. The Project/Task Management tool that people would rather agonize over rather than actually doing the project or the task itself
160 |
161 | ### It's Not for Me
162 | Not something the user wants to do, but something *you* want the user to do
163 | You want people to collaborate better, but do *they* want to collaborate better, or more importantly, are they willing to invest in the collaboration
164 |
165 | ### It's in the algorithm / it's an engineering problem
166 | The problem you see -- perhaps one of crushing bureaucratic incompetence or disorganized citizens -- probably can't be fixed with a website. That said, a digital tool might be designed *For Official Adoption*.
167 |
168 | ### They’ll visit it all the time
169 | Apps on my home screen: Google, Facebook, the New York Times. Apps that will never be on my home screen: yours.
170 |
171 | ## Types of Civic Applications
172 |
173 |
174 | The following is taken from [ESRI's "Civic Engagement Apps Fall into Seven Categories"](http://www.esri.com/news/arcuser/0312/civic-engagement-apps-fall-into-seven-categories.html) [though it could use improvement]:
175 |
176 | * **Public Information:** Maps are being used with greater frequency to communicate complex information that would not be quickly grasped in another format. These apps are effective at addressing transparency concerns, provide a channel for feedback, and communicate both where and why government money is being spent. Recovery.org, mapping the American Recovery and Reinvestment Act economic stimulus spending, is a good example of this type of app.
177 |
178 | * **Public Reporting:** The Federal Communications Commission (FCC) tapped into the power of crowdsourced information through the FCC Speed Test, an iPhone app that measures the quality and speed of a consumer's broadband connection. During the first six months it was available from the App Store, 1.2 million people downloaded the app and reported back information that helped the agency plan infrastructure expansion and determine policy. The captured data is visualized as a mapped surface that can be explored.
179 |
180 | * **Solicited Comments**: Apps don't have to be forever. When the Regional Transportation Commission of Washoe County, Nevada, wanted citizen comment on the Reno Sparks Bicycle and Pedestrian Master Plan, it worked with Esri partner CitySourced to develop an app that would let residents identify the locations for needed improvements, such as a crosswalk or a bike lane, simply by taking a photo of the location with a smartphone and writing comments in a form. These comments were captured and displayed on a web map. The app went up in summer 2010 and was taken down in early 2011.
181 |
182 | * **Unsolicited Comments**: Governments can learn about public opinion on issues and the effects of events through apps that gather constituents' posts on social media sites such as Twitter and Flickr. Social media maps on events such as the Gulf of Mexico oil spill aggregated and shared comments, photos, and videos that greatly enhanced the information available on conditions.
183 |
184 | * **Citizen as Sensor**: The Crime Tips app, from Esri partners The Omega Group and CitySourced, gives police many more eyes on the street. The iPhone/iPod/iPad app lets the user learn which crimes are happening nearby as well as anonymously report crime tips that will be forwarded to authorities.
185 |
186 | * **Volunteerism**: The Lifesaving App for the Android and iPhone, developed for the San Ramon Valley Fire Protection District by the nonprofit PulsePoint Foundation, crowdsources Good Samaritans. In instances of cardiac arrest, time is vital. The Lifesaving App lets smartphone users volunteer to be notified if someone nearby needs CPR. When a 911 call is received, the nearest CPR volunteer, who is in the best position to respond in timely fashion, receives information on the incident.
187 |
188 | * **Citizen as Scientist**: Individuals can contribute to collective knowledge with these apps. The free Mojave Desert Tortoise app lets users take a photo, find out more about this endangered species, and note location and other information about an individual tortoise.
189 |
190 |
191 |
--------------------------------------------------------------------------------
/html_generator/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile ~/.gitignore_global
6 |
7 | # Ignore bundler config
8 | /.bundle
9 | /vendor/bundle
10 |
11 | # Ignore the build directory
12 | /build
13 |
14 | # Ignore Sass' cache
15 | /.sass-cache
16 |
17 | # Ignore .DS_store file
18 | .DS_Store
19 |
--------------------------------------------------------------------------------
/html_generator/Gemfile:
--------------------------------------------------------------------------------
1 | source 'http://rubygems.org'
2 |
3 | gem 'middleman', '~>3.2.0'
4 | gem 'haml'
5 | gem 'redcarpet'
6 | gem 'nokogiri'
7 |
8 | gem 'compass'
9 | gem 'bootstrap-sass', '~> 3.0.2.0'
10 |
11 | gem 'middleman-livereload', '~> 3.1.0'
12 | gem 'middleman-pry'
13 |
14 | gem 'middleman-gh-pages'
15 |
--------------------------------------------------------------------------------
/html_generator/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: http://rubygems.org/
3 | specs:
4 | activesupport (3.2.17)
5 | i18n (~> 0.6, >= 0.6.4)
6 | multi_json (~> 1.0)
7 | bootstrap-sass (3.0.2.0)
8 | sass (~> 3.2)
9 | chunky_png (1.3.0)
10 | coderay (1.1.0)
11 | coffee-script (2.2.0)
12 | coffee-script-source
13 | execjs
14 | coffee-script-source (1.7.0)
15 | compass (0.12.2)
16 | chunky_png (~> 1.2)
17 | fssm (>= 0.2.7)
18 | sass (~> 3.1)
19 | em-websocket (0.5.0)
20 | eventmachine (>= 0.12.9)
21 | http_parser.rb (~> 0.5.3)
22 | eventmachine (1.0.3)
23 | execjs (1.4.0)
24 | multi_json (~> 1.0)
25 | ffi (1.9.3)
26 | fssm (0.2.10)
27 | haml (4.0.5)
28 | tilt
29 | hike (1.2.3)
30 | http_parser.rb (0.5.3)
31 | i18n (0.6.9)
32 | json (1.8.1)
33 | kramdown (1.3.2)
34 | listen (1.3.1)
35 | rb-fsevent (>= 0.9.3)
36 | rb-inotify (>= 0.9)
37 | rb-kqueue (>= 0.2)
38 | method_source (0.8.2)
39 | middleman (3.2.2)
40 | coffee-script (~> 2.2.0)
41 | compass (>= 0.12.2)
42 | execjs (~> 1.4.0)
43 | haml (>= 3.1.6)
44 | kramdown (~> 1.2)
45 | middleman-core (= 3.2.2)
46 | middleman-sprockets (>= 3.1.2)
47 | sass (>= 3.1.20)
48 | uglifier (~> 2.4.0)
49 | middleman-core (3.2.2)
50 | activesupport (~> 3.2.6)
51 | bundler (~> 1.1)
52 | i18n (~> 0.6.9)
53 | listen (~> 1.1)
54 | rack (>= 1.4.5)
55 | rack-test (~> 0.6.1)
56 | thor (>= 0.15.2, < 2.0)
57 | tilt (~> 1.4.1)
58 | middleman-gh-pages (0.0.3)
59 | rake (> 0.9.3)
60 | middleman-livereload (3.1.1)
61 | em-websocket (>= 0.2.0)
62 | middleman-core (>= 3.0.2)
63 | multi_json (~> 1.0)
64 | rack-livereload
65 | middleman-pry (0.0.3)
66 | middleman-core (>= 3.2.2)
67 | pry (>= 0.9.12)
68 | middleman-sprockets (3.2.0)
69 | middleman-core (~> 3.2)
70 | sprockets (~> 2.1)
71 | sprockets-helpers (~> 1.0.0)
72 | sprockets-sass (~> 1.0.0)
73 | mini_portile (0.5.2)
74 | multi_json (1.8.4)
75 | nokogiri (1.6.1)
76 | mini_portile (~> 0.5.0)
77 | pry (0.9.12.6)
78 | coderay (~> 1.0)
79 | method_source (~> 0.8)
80 | slop (~> 3.4)
81 | rack (1.5.2)
82 | rack-livereload (0.3.15)
83 | rack
84 | rack-test (0.6.2)
85 | rack (>= 1.0)
86 | rake (10.1.1)
87 | rb-fsevent (0.9.4)
88 | rb-inotify (0.9.3)
89 | ffi (>= 0.5.0)
90 | rb-kqueue (0.2.2)
91 | ffi (>= 0.5.0)
92 | redcarpet (3.1.1)
93 | sass (3.2.14)
94 | slop (3.4.7)
95 | sprockets (2.11.0)
96 | hike (~> 1.2)
97 | multi_json (~> 1.0)
98 | rack (~> 1.0)
99 | tilt (~> 1.1, != 1.3.0)
100 | sprockets-helpers (1.0.1)
101 | sprockets (~> 2.0)
102 | sprockets-sass (1.0.3)
103 | sprockets (~> 2.0)
104 | tilt (~> 1.1)
105 | thor (0.18.1)
106 | tilt (1.4.1)
107 | uglifier (2.4.0)
108 | execjs (>= 0.3.0)
109 | json (>= 1.8.0)
110 |
111 | PLATFORMS
112 | ruby
113 |
114 | DEPENDENCIES
115 | bootstrap-sass (~> 3.0.2.0)
116 | compass
117 | haml
118 | middleman (~> 3.2.0)
119 | middleman-gh-pages
120 | middleman-livereload (~> 3.1.0)
121 | middleman-pry
122 | nokogiri
123 | redcarpet
124 |
--------------------------------------------------------------------------------
/html_generator/Rakefile:
--------------------------------------------------------------------------------
1 | ##
2 | # Copied from middleman-gh-pages
3 | # Modified to link to non-standard project home
4 | # https://github.com/neo/middleman-gh-pages
5 | ##
6 |
7 | require 'fileutils'
8 |
9 | def remote_name
10 | ENV.fetch("REMOTE_NAME", "origin")
11 | end
12 |
13 | PROJECT_ROOT = File.join(`git rev-parse --show-toplevel`.strip, 'html_generator')
14 | BUILD_DIR = File.join(PROJECT_ROOT, "build")
15 | GH_PAGES_REF = File.join(BUILD_DIR, ".git/refs/remotes/#{remote_name}/gh-pages")
16 |
17 | directory BUILD_DIR
18 |
19 | file GH_PAGES_REF => BUILD_DIR do
20 | repo_url = nil
21 |
22 | cd PROJECT_ROOT do
23 | repo_url = `git config --get remote.#{remote_name}.url`.strip
24 | end
25 |
26 | cd BUILD_DIR do
27 | sh "git init"
28 | sh "git remote add #{remote_name} #{repo_url}"
29 | sh "git fetch #{remote_name}"
30 |
31 | if `git branch -r` =~ /gh-pages/
32 | sh "git checkout gh-pages"
33 | else
34 | sh "git checkout --orphan gh-pages"
35 | sh "touch index.html"
36 | sh "git add ."
37 | sh "git commit -m 'initial gh-pages commit'"
38 | sh "git push #{remote_name} gh-pages"
39 | end
40 | end
41 | end
42 |
43 | # Alias to something meaningful
44 | task :prepare_git_remote_in_build_dir => GH_PAGES_REF
45 |
46 | # Fetch upstream changes on gh-pages branch
47 | task :sync do
48 | cd BUILD_DIR do
49 | sh "git fetch #{remote_name}"
50 | sh "git reset --hard #{remote_name}/gh-pages"
51 | end
52 | end
53 |
54 | # Prevent accidental publishing before committing changes
55 | task :not_dirty do
56 | puts "***#{ENV['ALLOW_DIRTY']}***"
57 | unless ENV['ALLOW_DIRTY']
58 | fail "Directory not clean" if /nothing to commit/ !~ `git status`
59 | end
60 | end
61 |
62 | desc "Compile all files into the build directory"
63 | task :build do
64 | cd PROJECT_ROOT do
65 | sh "bundle exec middleman build --clean"
66 | end
67 | end
68 |
69 | desc "Build and publish to Github Pages"
70 | task :publish => [:not_dirty, :prepare_git_remote_in_build_dir, :sync, :build] do
71 | message = nil
72 | suffix = ENV["COMMIT_MESSAGE_SUFFIX"]
73 |
74 | cd PROJECT_ROOT do
75 | head = `git log --pretty="%h" -n1`.strip
76 | message = ["Site updated to #{head}", suffix].compact.join("\n\n")
77 | end
78 |
79 | cd BUILD_DIR do
80 | sh 'git add --all'
81 | if /nothing to commit/ =~ `git status`
82 | puts "No changes to commit."
83 | else
84 | sh "git commit -m \"#{message}\""
85 | end
86 | sh "git push #{remote_name} gh-pages"
87 | end
88 | end
89 |
--------------------------------------------------------------------------------
/html_generator/config.rb:
--------------------------------------------------------------------------------
1 | require 'pathname'
2 | require 'ostruct'
3 | require 'nokogiri'
4 |
5 | PROJECT_ROOT = Pathname.new("#{Middleman::Application.root}/..")
6 | ###
7 | # Compass
8 | ###
9 |
10 | # Change Compass configuration
11 | # compass_config do |config|
12 | # config.output_style = :compact
13 | # end
14 |
15 | ###
16 | # Page options, layouts, aliases and proxies
17 | ###
18 |
19 | # Per-page layout changes:
20 | #
21 | # With no layout
22 | # page "/path/to/file.html", :layout => false
23 | #
24 | # With alternative layout
25 | # page "/path/to/file.html", :layout => :otherlayout
26 | #
27 | # A path which all have the same layout
28 | # with_layout :admin do
29 | # page "/admin/*"
30 | # end
31 |
32 | # Proxy pages (http://middlemanapp.com/basics/dynamic-pages/)
33 | # proxy "/this-page-has-no-template.html", "/template-file.html", :locals => {
34 | # :which_fake_page => "Rendering a fake page with a local variable" }
35 |
36 | ###
37 | # Helpers
38 | ###
39 |
40 | # Automatic image dimensions on image_tag helper
41 | # activate :automatic_image_sizes
42 |
43 | # Reload the browser automatically whenever files change
44 | # activate :livereload
45 |
46 | # Methods defined in the helpers block are available in templates
47 | # helpers do
48 | # def some_helper
49 | # "Helping"
50 | # end
51 | # end
52 |
53 | set :css_dir, 'stylesheets'
54 |
55 | set :js_dir, 'javascripts'
56 |
57 | set :images_dir, 'images'
58 |
59 | markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
60 |
61 | # Dynamically use the README.md file from the project root as index.html
62 | readme = OpenStruct.new
63 | readme.markdown = Pathname.new("#{PROJECT_ROOT}/README.md").open.read
64 | readme.html = markdown.render(readme.markdown)
65 | readme.dom = Nokogiri::HTML(readme.html)
66 |
67 | def fragment_id(text)
68 | sanitary = text.downcase.gsub(/\A^[a-z ]\z/, '')
69 | "#{sanitary.split(' ').join('_')}"
70 | end
71 |
72 | # Add fragment identifiers to headers
73 | readme.html = readme.dom.tap do |dom|
74 | dom.css('h2,h3,h4').each do |header|
75 | header[:id] = fragment_id(header.text)
76 | end
77 | end.to_html
78 |
79 | # generate the table of contents
80 | readme.toc = readme.dom.css('h3').map do |header|
81 | OpenStruct.new(
82 | link: "##{fragment_id(header.text)}",
83 | text: header.text
84 | )
85 | end
86 |
87 | proxy "/index.html", "/readme.html", locals: {
88 | content: readme.html,
89 | toc: readme.toc
90 | }, ignore: true
91 |
92 | # Build-specific configuration
93 | configure :build do
94 | activate :minify_css
95 | activate :minify_javascript
96 |
97 | activate :asset_hash
98 |
99 | # Use relative URLs
100 | activate :relative_assets
101 |
102 | # Or use a different image path
103 | # set :http_prefix, "/Content/images/"
104 | end
105 |
--------------------------------------------------------------------------------
/html_generator/scripts/generate-key-mac.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # On OS X, use this script to generate an encrypted deployment key for Travis CI.
4 |
5 | # Dependencies:
6 | # gem install travis
7 | # brew install coreutils
8 |
9 | # Also, you must enable travis for the repository that holds the builds
10 |
11 | if [ $# -lt 1 ]; then
12 | echo "usage: $0 /"
13 | exit 1
14 | fi
15 |
16 | REPO=$1
17 |
18 | KEY_DIR=/tmp/civic-tech-patterns-key
19 | mkdir -p $KEY_DIR
20 |
21 | echo "Generating key pair..."
22 | ssh-keygen -q -f $KEY_DIR/id_rsa -P ''
23 |
24 | echo "Encrypting private key..."
25 | base64 --break=0 $KEY_DIR/id_rsa > $KEY_DIR/id_rsa_base64
26 | ENCRYPTION_FILTER="echo \$(echo \"- secure: \")\$(travis encrypt \"\$FILE='\`cat $FILE\`'\" -r $REPO)"
27 | gsplit --bytes=100 --numeric-suffixes --suffix-length=2 --filter="$ENCRYPTION_FILTER" $KEY_DIR/id_rsa_base64 id_rsa_
28 |
29 | echo
30 | echo "1. Add the above lines to your .travis.yml file."
31 | echo "2. Call read-key.sh from your .travis.yml file."
32 | echo "3. Add $KEY_DIR/id_rsa.pub as a deploy key to the destination Github repo."
33 |
34 |
35 | # To reconstitute the private SSH key from within the Travis-CI build (typically from 'before_script')
36 | # echo -n $id_rsa_{00..30} >> ~/.ssh/id_rsa_base64
37 | # base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
38 | # chmod 600 ~/.ssh/id_rsa
39 | # echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
40 |
--------------------------------------------------------------------------------
/html_generator/scripts/predeploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # extract private key from decrypted environment variables stored in .travis.yml
4 | echo -n $id_rsa_{00..30} >> ~/.ssh/id_rsa_base64
5 | base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
6 | chmod 600 ~/.ssh/id_rsa
7 |
8 | # anyone can read the build log, so it MUST NOT contain any sensitive data
9 | set -x
10 |
11 | # add github's public key
12 | echo "|1|qPmmP7LVZ7Qbpk7AylmkfR0FApQ=|WUy1WS3F4qcr3R5Sc728778goPw= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==" >> ~/.ssh/known_hosts
13 |
14 | # Set the git author
15 | git config user.name "Travis CI"
16 | git config user.email "travis@travis-ci.org"
17 |
--------------------------------------------------------------------------------
/html_generator/source/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeforamerica/civic-tech-patterns/2ae48442a11068e84cc776dff24ecc0408ed9aae/html_generator/source/images/.gitkeep
--------------------------------------------------------------------------------
/html_generator/source/javascripts/application.js.coffee:
--------------------------------------------------------------------------------
1 | #= require bootstrap
2 | #
3 | #= require_tree .
4 |
--------------------------------------------------------------------------------
/html_generator/source/layouts/layout.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | <%= current_page.data.title || "The Middleman" %>
11 |
12 | <%= stylesheet_link_tag "application" %>
13 | <%= javascript_include_tag "application" %>
14 |
15 |
16 |
17 | <%= yield %>
18 |
19 |
20 |
--------------------------------------------------------------------------------
/html_generator/source/readme.html.haml:
--------------------------------------------------------------------------------
1 |
2 |
3 | - toc.each do |entry|
4 | = link_to entry.text, entry.link
5 |
6 | = content
7 |
--------------------------------------------------------------------------------
/html_generator/source/stylesheets/application.css.sass:
--------------------------------------------------------------------------------
1 | @import "compass"
2 | @import "bootstrap"
3 |
--------------------------------------------------------------------------------