diff --git a/.eleventy.js b/.eleventy.js index d2300fb39..e5eb13398 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,33 +1,33 @@ const fs = require('fs'); -const { EleventyRenderPlugin } = require("@11ty/eleventy"); +const { EleventyRenderPlugin } = require('@11ty/eleventy'); const pluginRss = require('@11ty/eleventy-plugin-rss'); const pluginNavigation = require('@11ty/eleventy-navigation'); const markdownIt = require('markdown-it'); const markdownItAttrs = require('markdown-it-attrs'); const markdownItAnchor = require('markdown-it-anchor'); const markdownItFootnote = require('markdown-it-footnote'); +const svgSprite = require('eleventy-plugin-svg-sprite'); +const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight'); +const yaml = require('js-yaml'); +const { parse } = require('csv-parse/sync'); /* eslint-disable-line import/no-unresolved */ const { readableDate , htmlDateString , head , min , filterTagList , embed - , team_photo - , team_link - , find_collection + , teamPhoto + , teamLink + , findCollection , markdownify - , weighted_sort - , in_groups + , weightedSort + , inGroups , oembed - , relative_url - , match_posts } = require("./config/filters"); -const { headingLinks } = require("./config/headingLinks"); -const { contrastRatio, humanReadableContrastRatio } = require("./config/wcagColorContrast"); -const privateLinks = require ('./config/privateLinksList.js'); -const svgSprite = require("eleventy-plugin-svg-sprite"); -const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight"); -const yaml = require("js-yaml"); -const { parse } = require('csv-parse/sync'); + , asRelativeUrl + , matchPosts } = require('./config/filters'); +const { headingLinks } = require('./config/headingLinks'); +const { contrastRatio, humanReadableContrastRatio } = require('./config/wcagColorContrast'); +const privateLinks = require ('./config/privateLinksList'); const { imageShortcode, imageWithClassShortcode } = require('./config'); @@ -39,15 +39,18 @@ module.exports = function (config) { config.addPlugin(EleventyRenderPlugin); + // copying assets did something weird and this fixed it + config.setServerPassthroughCopyBehavior('passthrough'); // Copy the `admin` folders to the output config.addPassthroughCopy('admin'); + config.addPassthroughCopy('assets'); // Copy USWDS init JS so we can load it in HEAD to prevent banner flashing config.addPassthroughCopy({'./node_modules/@uswds/uswds/dist/js/uswds-init.js': 'assets/js/uswds-init.js'}); // Specific scripts to guides - config.addPassthroughCopy("./assets/_common/js/*"); - config.addPassthroughCopy("./assets/**/js/*"); + config.addPassthroughCopy('./assets/_common/js/*'); + config.addPassthroughCopy('./assets/**/js/*'); // @TODO This is one place where the _site/img folder gets produced // Let's find a way to keep everything in assets @@ -61,16 +64,16 @@ module.exports = function (config) { config.addPlugin(pluginRss); config.addPlugin(pluginNavigation); - //// SVG Sprite Plugin for USWDS USWDS icons + /// / SVG Sprite Plugin for USWDS USWDS icons config.addPlugin(svgSprite, { - path: "./node_modules/@uswds/uswds/dist/img/uswds-icons", + path: './node_modules/@uswds/uswds/dist/img/uswds-icons', svgSpriteShortcode: 'uswds_icons_sprite', svgShortcode: 'uswds_icons' }); - //// SVG Sprite Plugin for USWDS USA icons + /// / SVG Sprite Plugin for USWDS USA icons config.addPlugin(svgSprite, { - path: "./node_modules/@uswds/uswds/dist/img/usa-icons", + path: './node_modules/@uswds/uswds/dist/img/usa-icons', svgSpriteShortcode: 'usa_icons_sprite', svgShortcode: 'usa_icons' }); @@ -79,11 +82,9 @@ module.exports = function (config) { config.addPlugin(syntaxHighlight); // Allow yaml to be used in the _data dir - config.addDataExtension("yml, yaml", contents => yaml.load(contents)); + config.addDataExtension('yml, yaml', contents => yaml.load(contents)); - config.addDataExtension("csv", (contents) => { - return parse(contents, {columns: true, skip_empty_lines: true}); - }); + config.addDataExtension('csv', (contents) => parse(contents, {columns: true, skip_empty_lines: true})); // Filters @@ -98,25 +99,17 @@ module.exports = function (config) { // Add an iframe / embedded content config.addFilter('embed', embed); // Add a photo for an 18F team member - config.addFilter('team_photo', team_photo); + config.addFilter('team_photo', teamPhoto); // Add a link to an 18F team member's author page - config.addFilter('team_link', team_link); - config.addFilter('find_collection', find_collection); - config.addFilter('weighted_sort', weighted_sort); - config.addFilter('in_groups', in_groups); + config.addFilter('team_link', teamLink); + config.addFilter('find_collection', findCollection); + config.addFilter('weighted_sort', weightedSort); + config.addFilter('in_groups', inGroups); config.addShortcode('oembed', oembed); - config.addFilter('relative_url', relative_url); - config.addFilter('match_posts', match_posts); - config.addFilter("limit", function (arr, limit) { - return arr.slice(0, limit); - }); - config.addFilter('matching', function(collection, author) { - return collection.filter((post) => { - return post.data.authors.includes(author) - }); - }); - - // FIXME (see other FIXME) + config.addFilter('relative_url', asRelativeUrl); + config.addFilter('match_posts', matchPosts); + config.addFilter('limit', (arr, limit) => arr.slice(0, limit)); + config.addFilter('matching', (collection, author) => collection.filter((post) => post.data.authors.includes(author))); config.addFilter('markdownify', markdownify); // Color contrast checkers for the color matrix in the Brand guide @@ -125,41 +118,34 @@ module.exports = function (config) { // Create absolute urls config.addFilter('asAbsoluteUrl', (relativeUrl) => { - const host = siteData.host; + const {host} = siteData; return new URL(relativeUrl, host).href; }); - config.addFilter("makeUppercase", (value) => { - return value.toUpperCase(); - }); + config.addFilter('makeUppercase', (value) => value.toUpperCase()); - config.addFilter("capitalize", (value) =>{ - return value.charAt(0).toUpperCase() + value.slice(1); - }); + config.addFilter('capitalize', (value) =>value.charAt(0).toUpperCase() + value.slice(1)); // Converts strings or dates to date objects const dateObject = ((date) => { switch(typeof date) { - case "object": return date; - case "string": return new Date(date) + case 'object': return date; + case 'string': return new Date(date); + default: throw new Error(`Expected date (${date}) to be string or object`) } }) // Generates the "yyyy/mm/dd" part of permalinks for blog posts // @example date is Jan 1, 2020 // returns "2020/01/01" - config.addFilter("toDatePath", (date) => { - return dateObject(date).toISOString().split('T')[0].split('-').join('/') - }); + config.addFilter('toDatePath', (date) => dateObject(date).toISOString().split('T')[0].split('-').join('/')); // TODO: Not sure this is returning exactly the right string, re: datetimes - config.addFilter("date_to_xmlschema", (date) => { - return dateObject(date).toISOString() - }); + config.addFilter('date_to_xmlschema', (date) => dateObject(date).toISOString()); // Create an array of all tags - config.addCollection('tagList', function (collection) { - let tagSet = new Set(); + config.addCollection('tagList', (collection) => { + const tagSet = new Set(); collection.getAll().forEach((item) => { (item.data.tags || []).forEach((tag) => tagSet.add(tag)); }); @@ -167,12 +153,11 @@ module.exports = function (config) { return filterTagList([...tagSet]); }); - config.addCollection('post', function (collection) { - return collection.getFilteredByGlob('content/posts/*.md') - }); + config.addCollection('post', (collection) => collection.getFilteredByGlob('content/posts/*.md')); + config.addCollection('service', (collection) => collection.getFilteredByGlob('content/pages/projects/services/*.md')); // Customize Markdown library and settings - let markdownLibrary = markdownIt({ + const markdownLibrary = markdownIt({ html: true, breaks: false, linkify: false, @@ -213,7 +198,7 @@ module.exports = function (config) { const baseURL = new URL('https://guides.18f.gov/'); const hrefValue = token.attrGet('href'); - if (!(new URL(hrefValue, baseURL).hostname.endsWith(".gov"))) { + if (!(new URL(hrefValue, baseURL).hostname.endsWith('.gov'))) { // Add the external link class if it hasn't been added yet if (!(token.attrGet('class')) || !(token.attrGet('class').includes('usa-link--external'))) { token.attrJoin('class', 'usa-link usa-link--external'); @@ -224,7 +209,7 @@ module.exports = function (config) { token.attrJoin('rel', 'noreferrer'); } } - return openDefaultRender(tokens, idx, options, env, self) + `${prefixIcon}`; + return `${openDefaultRender(tokens, idx, options, env, self) }${prefixIcon}`; }; const defaultHtmlBlockRender = markdownLibrary.renderer.rules.html_block || @@ -234,10 +219,10 @@ module.exports = function (config) { markdownLibrary.renderer.rules.html_block = (tokens, idx, options, env, self) => { const token = tokens[idx]; - let content = token.content; + let {content} = token; // Capture the class portion of the element if it exists so it can be interacted with later // https://regexr.com/7udrd - const hrefRE = /|href=\"([^"]*)\"/g; + const hrefRE = /|href="([^"]*)"/g; const htmlIncludesLinks = content.includes('http') && hrefRE.test(token.content); if (htmlIncludesLinks) { @@ -248,7 +233,7 @@ module.exports = function (config) { if (!anchorElement.includes('class=')) { if (!anchorElement.includes('usa-link--external')) { // Since no class is present, we can safely just append our classes after the href property - const newUrl = anchorElement + ' class="usa-link usa-link--external"'; + const newUrl = `${anchorElement } class="usa-link usa-link--external"`; content = content.replace(anchorElement, newUrl); tokens[idx].content = content; } @@ -256,7 +241,7 @@ module.exports = function (config) { // Handle URLs with classes already present const classRE = /class="([^"]*)"/; const [classString, oldClassList] = anchorElement.match(classRE); - const newClassList = oldClassList + ' usa-link usa-link--external'; + const newClassList = `${oldClassList } usa-link usa-link--external`; // If someone uses the class property but doesn't actually put any classes in it, the class list will be empty if (classString === 'class=""') { @@ -283,10 +268,10 @@ module.exports = function (config) { markdownLibrary.renderer.rules.html_inline = (tokens, idx, options, env, self) => { const token=tokens[idx]; if (linkOpenRE.test(token.content) && token.content.includes('http')) { - let content = token.content; + let {content} = token; - //Add private link icon - const hrefRE = /href=\"([^"]*)/; + // Add private link icon + const hrefRE = /href="([^"]*)/; // get the matching capture group const contentUrl = content.match(hrefRE)[1]; if (privateLinks.some((privateLink) => contentUrl.indexOf(privateLink) >= 0)) { @@ -329,13 +314,13 @@ module.exports = function (config) { // Override Browsersync defaults (used only with --serve) config.setBrowserSyncConfig({ callbacks: { - ready: function (err, browserSync) { - const content_404 = fs.readFileSync('_site/404/index.html'); + ready (err, browserSync) { + const content404 = fs.readFileSync('_site/404/index.html'); browserSync.addMiddleware('*', (req, res) => { // Provides the 404 content without redirect. res.writeHead(404, { 'Content-Type': 'text/html; charset=UTF-8' }); - res.write(content_404); + res.write(content404); res.end(); }); }, @@ -347,12 +332,10 @@ module.exports = function (config) { // Set image shortcodes config.addLiquidShortcode('image', imageShortcode); config.addLiquidShortcode('image_with_class', imageWithClassShortcode); - config.addLiquidShortcode("uswds_icon", function (name) { - return ` + config.addLiquidShortcode('uswds_icon', (name) => ` `; - }); + `); // If BASEURL env variable exists, update pathPrefix to the BASEURL if (process.env.BASEURL) { @@ -385,7 +368,7 @@ module.exports = function (config) { // You can also pass this in on the command line using `--pathprefix` // Optional (default is shown) - pathPrefix: pathPrefix, + pathPrefix, // ----------------------------------------------------------------- // These are all optional (defaults are shown): diff --git a/.eslintrc.json b/.eslintrc.json index 3663bd413..c3b42b59e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,7 +5,7 @@ "es2021": true, "mocha": true }, - "ignorePatterns": ["/_site"], + "ignorePatterns": ["_site/", "assets/", "!.eleventy.js"], "extends": ["eslint-config-airbnb-base", "prettier"], "parserOptions": { "ecmaVersion": "latest", diff --git a/_data/assetPaths.json b/_data/assetPaths.json index 0b83efda4..be5f4dc8f 100644 --- a/_data/assetPaths.json +++ b/_data/assetPaths.json @@ -1,13 +1,8 @@ { - "admi.js": "/assets/_common/js/admin.js", - "ap.js": "/assets/_common/js/app.js", - "inde.html": "/assets/presentations/presentation-README/index.html", "admin.js": "/assets/js/admin-3AAZDPS4.js", "admin.map": "/assets/js/admin-3AAZDPS4.js.map", "app.js": "/assets/js/app-VJ5WPKYD.js", "app.map": "/assets/js/app-VJ5WPKYD.js.map", - "external.js": "/assets/js/external-links.js", - "uswds.js": "/assets/js/uswds-init.js", "styles.css": "/assets/styles/styles-YNYM6ERT.css", "styles.map": "/assets/styles/styles-YNYM6ERT.css.map" } \ No newline at end of file diff --git a/_includes/card-with-image-guides.html b/_includes/card-with-image-guides.html index 178a9bd29..ad55c1a65 100644 --- a/_includes/card-with-image-guides.html +++ b/_includes/card-with-image-guides.html @@ -1,9 +1,9 @@ {% comment %} -This partial outputs a card with a heading, icon, descriptive text, a link, and, optionally, a hero image. -It was spun off from the "card-with-image" partial to accomodate the unique needs of the guides index page. -The whole card is no longer a clickable link. In the future, these might be condensed back down -into a single partial and class, but it will probably require some more conditional statements -because the behaviors are so different. +This partial outputs a card with a heading, icon, descriptive text, a link, and, optionally, a hero image. +It was spun off from the "card-with-image" partial to accomodate the unique needs of the guides index page. +The whole card is no longer a clickable link. In the future, these might be condensed back down +into a single partial and class, but it will probably require some more conditional statements +because the behaviors are so different. The expected arguments for this partial are: link_url - the url the links on the card will link to (href) @@ -23,27 +23,27 @@ - {% if include.hero_url %} + {% if hero_url %}
- +
{% endif %}
-
+
{% capture card_image %} - {{- include.image_alt_text -}} {% endcapture %} {% capture card_text %} -

{{ include.text_content }}

+

{{ text_content }}

{% endcapture %} - {% if include.image_side == "right" %} + {% if image_side == "right" %} {{ card_text }} {{ card_image }} {% else %} @@ -52,8 +52,8 @@

{{ include.text_content }}

{% endif %}
- -

{{ include.text_descrip }}

-
Read {{ include.text_content }} guide + +

{{ text_descrip }}

+ Read {{ text_content }} guide
diff --git a/_includes/card-with-image.html b/_includes/card-with-image.html index be02673ab..0b583e980 100644 --- a/_includes/card-with-image.html +++ b/_includes/card-with-image.html @@ -1,5 +1,5 @@ {% comment %} -This partial outputs a card with image and text. The whole card is a clickable link. +This partial outputs a card with image and text. The whole card is a clickable link. The expected arguments for this partial are: link_url - the url the card will link to (href) @@ -13,23 +13,23 @@ image_size - if set to "md" will set the max image size to 8 units. Otherwise the image will default to a max size of 6 units. {% endcomment %} - -
+
{% capture card_image %} - {{- include.image_alt_text -}} {% endcapture %} {% capture card_text %} -

{{ include.text_content }}

+

{{ text_content }}

{% endcapture %} -{% if include.image_side == "right" %} +{% if image_side == "right" %} {{ card_text }} {{ card_image }} {% else %} diff --git a/_includes/layouts/author.html b/_includes/layouts/author.html index 57e3279f6..4124aa60f 100644 --- a/_includes/layouts/author.html +++ b/_includes/layouts/author.html @@ -8,7 +8,7 @@ Layout for author page with their blog posts {% endcomment %} -{% assign matching_posts = collections.post | matching: author.id | sort: 'date' | limit: 3 %} +{% assign matching_posts = collections.post | matching: author.id | sort: 'date' | reverse %}
diff --git a/_includes/logo.html b/_includes/logo.html index ff725014d..4d5db4ec7 100644 --- a/_includes/logo.html +++ b/_includes/logo.html @@ -1,10 +1,3 @@ diff --git a/_includes/meta.html b/_includes/meta.html index d93e7b65f..b6a813f35 100644 --- a/_includes/meta.html +++ b/_includes/meta.html @@ -3,58 +3,56 @@ to modify some of the meta-data for the site, this is the place to do it. {% endcomment %} - - - - - {%- unless env.production %} - - {%- endunless %} - - - - - + + + +{%- unless env.production %} + +{%- endunless %} + + + + + - {% if seo_title %} - {% assign page_title = seo_title | append: ' | 18F ' %} - {% else %} - {% assign page_title = title | append: ' | 18F ' %} - {% endif %} +{% if seo_title %} + {% assign page_title = seo_title | append: ' | 18F ' %} +{% else %} + {% assign page_title = title | append: ' | 18F ' %} +{% endif %} - {{ page_title }} - - - +{{ page_title }} + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - {% comment -%} - This prism CDN is for Prismjs, which is used in eleventy's syntax highlighting plugin. Eleventy recommends using one of Prism's CDN's to provide the css. More info in the docs: https://www.11ty.dev/docs/plugins/syntaxhighlight/ - {% endcomment %} - - - - + +{% comment -%} + This prism CDN is for Prismjs, which is used in eleventy's syntax highlighting plugin. Eleventy recommends using one of Prism's CDN's to provide the css. More info in the docs: https://www.11ty.dev/docs/plugins/syntaxhighlight/ +{% endcomment %} + + + diff --git a/_includes/testimonial.html b/_includes/testimonial.html index f4ea832fe..bb907b11d 100644 --- a/_includes/testimonial.html +++ b/_includes/testimonial.html @@ -3,14 +3,16 @@ {% assign figcaption_class = "font-sans-md line-height-sans-3 margin-top-3 text-white" %} {% assign organization_class = "font-sans-sm" %}
-

-
- {{ include.quote }} -
-
- —{{ include.attribution }}{%- if include.position %}, {{ include.position }}{%- endif %}
- {{ include.organization }} -
+
+

+
+ {{ include.quote }} +
+
+ —{{ attribution }}{%- if position %}, {{ position }}{%- endif %}
+ {{ organization }} +
+
{% else %} {% assign blockquote_class = "font-sans-lg tablet:font-sans-xl line-height-sans-3 measure-5 margin-top-4 text-center text-ls-05 text-white" %} @@ -19,14 +21,16 @@
-

-
- {{ include.quote }} -
-
- —{{ include.attribution }}{%- if include.position %}, {{ include.position }}{%- endif %} {%- if include.organization %}
- {{ include.organization }}{%- endif %} -
+
+

+
+ {{ quote }} +
+
+ —{{ attribution }}{%- if position %}, {{ position }}{%- endif %} {%- if organization %}
+ {{ organization }}{%- endif %} +
+
diff --git a/assets/blog/collaborative-brainstorming-session..png b/assets/blog/collaborative-brainstorming-session.png similarity index 100% rename from assets/blog/collaborative-brainstorming-session..png rename to assets/blog/collaborative-brainstorming-session.png diff --git a/content/pages/principles/18FPartnershipPrinciples.pdf b/assets/presentations/18FPartnershipPrinciples.pdf similarity index 100% rename from content/pages/principles/18FPartnershipPrinciples.pdf rename to assets/presentations/18FPartnershipPrinciples.pdf diff --git a/config/filters.js b/config/filters.js index 121536519..da1f81a1d 100644 --- a/config/filters.js +++ b/config/filters.js @@ -1,8 +1,10 @@ // Keep filter source code here. const fs = require('fs'); -const { parse } = require('csv-parse/sync'); const { DateTime } = require('luxon'); -const { imageShortcode, imageWithClassShortcode } = require('./index'); +const markdownIt = require('markdown-it'); +const { parse } = require('csv-parse/sync'); /* eslint-disable-line import/no-unresolved */ + +const { imageShortcode } = require('./index'); const readableDate = (dateObj) => DateTime.fromJSDate(dateObj, { zone: 'utc' }).toFormat( 'dd LLL yyyy', @@ -29,9 +31,7 @@ const filterTagList = (tags) => (tags || []).filter( (tag) => ['all', 'nav', 'post', 'posts'].indexOf(tag) === -1, ); -const embed = (url, title=url) => { - return `
` -} +const embed = (url, title=url) => `
` const teamData = parse( fs.readFileSync('./_data/team_members.csv', 'utf8'), { @@ -41,33 +41,33 @@ const teamData = parse( ); const findPerson = (id) => { - const maybePerson = teamData.find((person) => person.id == id); + const maybePerson = teamData.find((person) => person.id === id); if (maybePerson === undefined) { - console.log(id, "is undefined") + console.log(id, 'is undefined') } return maybePerson } const fullName = (person) => { - if (person.full_name != '') { + if (person.full_name !== '') { return person.full_name; - } else { - return `${person.first_name} ${person.last_name}` } + return `${person.first_name} ${person.last_name}` + } -const team_photo = (slug) => { +const teamPhoto = (slug) => { const maybePerson = findPerson(slug) const maybeImage = `assets/img/team/${slug}.jpg` - var imagePath; - var caption; - var placeholderImage; + let imagePath; + let caption; + let placeholderImage; if (fs.existsSync(maybeImage)) { imagePath = maybeImage; placeholderImage = false; } else { - imagePath = "assets/img/logos/18F-Logo-M.png"; + imagePath = 'assets/img/logos/18F-Logo-M.png'; placeholderImage = true; } @@ -78,32 +78,30 @@ const team_photo = (slug) => { caption = `Photo of 18F team member ${fullName(maybePerson)}`; } } else { - caption = "Placeholder photo for 18F team member"; + caption = 'Placeholder photo for 18F team member'; } return imageShortcode(imagePath, caption); } -const team_link = (slug) => { +const teamLink = (slug) => { const name = fullName(findPerson(slug)) - return `${name}` + return `${name}` } // TODO These all need implementation, they're just placeholders so the site builds at all -const find_collection = (site, collection) => { return [] } -const weighted_sort = (array, weight_name, sort_name) => { return array } -const in_groups = (array, groups) => { return array } -const oembed = (url) => { return `TODO EMBED ${url}` } -const relative_url = (url) => { return url } -const match_posts = (page, property="tags") => { return [] } - -// FIXME -// The markdownify filter in this site is mostly a smell, -// indicating that a different layout should be used. -// This is a placeholder, so I can get the site to build. -// My sense is it should not be used in production. -const markdownify = (content) => { return content } - +// TODO remove the eslint-disable directive after implementation +/* eslint-disable */ +const findCollection = (site, collection) => [] +const weightedSort = (array, weight_name, sort_name) => array +const inGroups = (array, groups) => array +const oembed = (url) => `TODO EMBED ${url}` +const asRelativeUrl = (url) => url +const matchPosts = (page, property='tags') => [] +/* eslint-enable */ + +const md = markdownIt({ html: true }); +const markdownify = (content) => md.render(content) module.exports = { readableDate, @@ -112,13 +110,13 @@ module.exports = { min, filterTagList, embed, - team_photo, - team_link, - find_collection, + teamPhoto, + teamLink, + findCollection, markdownify, - weighted_sort, - in_groups, + weightedSort, + inGroups, oembed, - relative_url, - match_posts, + asRelativeUrl, + matchPosts, }; diff --git a/content/pages/guides.html b/content/pages/guides.html new file mode 100644 index 000000000..f451c257d --- /dev/null +++ b/content/pages/guides.html @@ -0,0 +1,55 @@ +--- +title: Guides +permalink: /guides/ +layout: guides +lead: Principles and standards that shape our work +hide_footer_rule: true +--- +
+
+
+
+ 18F’s work with other agencies is built on user-centered development, testing to validate hypotheses, shipping often, and deploying products in the open. Below are the technical guides that bring those principles into our day-to-day work. +
+
+
+ {% for guide in site.data.guides %} + {% if guide.promoted %} +
+ {% include "card-with-image-guides.html" + text_content: guide.name + text_descrip: guide.description + link_url: guide.link + image_path: guide.image.dark + image_side: "right" + hero_url: guide.image.hero + %} +
+ {% endif %} + {% endfor %} +
+
+ {% for guide in site.data.guides %} + {% unless guide.promoted %} +
+ {% include "card-with-image-guides.html" + text_content: guide.name + text_descrip: guide.description + link_url: guide.link + image_path: guide.image.dark + image_side: "right" + %} +
+ {% endunless %} + {% endfor %} +
+
+
+ Beyond helping 18F staff do their best work, we hope these guides will inspire other federal agencies to adopt new practices. 18F’s projects with other federal agencies show that these techniques can help projects stay within budget, provide excellent value to the public, and fulfill federal rules. + + These guides, and all of 18F's work, are in the worldwide public domain. You are free to copy and adapt them as you choose. If you see something amiss or want to suggest a change, there are links at the bottom of each guide to help you contribute. +
+
+
+
+ diff --git a/content/pages/guides.md b/content/pages/guides.md deleted file mode 100644 index d63c93a91..000000000 --- a/content/pages/guides.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Guides -permalink: /guides/ -layout: guides -lead: Principles and standards that shape our work -hide_footer_rule: true ---- - -{% capture intro %} -18F’s work with other agencies is built on user-centered development, testing to validate hypotheses, shipping often, and deploying products in the open. Below are the technical guides that bring those principles into our day-to-day work. -{% endcapture %} - -{% capture public_domain %} -Beyond helping 18F staff do their best work, we hope these guides will inspire other federal agencies to adopt new practices. 18F’s projects with other federal agencies show that these techniques can help projects stay within budget, provide excellent value to the public, and fulfill federal rules. - -These guides, and all of 18F's work, are in the [worldwide public domain](https://github.com/18F/18f.gsa.gov/blob/main/LICENSE.md){:.usa-link--alt}. You are free to copy and adapt them as you choose. If you see something amiss or want to suggest a change, there are links at the bottom of each guide to help you contribute. -{% endcapture%} - -
-
-
-
- {{ intro | markdownify }} -
-
-
- {% for guide in site.data.guides %} - {% if guide.promoted %} -
- {% include "card-with-image-guides.html" - text_content=guide.name - text_descrip=guide.description - link_url=guide.link - image_path=guide.image.dark - image_side="right" - hero_url=guide.image.hero - %} -
- {% endif %} - {% endfor %} -
-
- {% for guide in site.data.guides %} - {% unless guide.promoted %} -
- {% include "card-with-image-guides.html" - text_content=guide.name - text_descrip=guide.description - link_url=guide.link - image_path=guide.image.dark - image_side="right" - %} -
- {% endunless %} - {% endfor %} -
-
-
- {{ public_domain | markdownify }} -
-
-
-
- diff --git a/content/pages/our-work.md b/content/pages/our-work.html similarity index 61% rename from content/pages/our-work.md rename to content/pages/our-work.html index df434e593..1f29809f8 100644 --- a/content/pages/our-work.md +++ b/content/pages/our-work.html @@ -13,7 +13,7 @@ - /what-we-deliver/new-ten/ --- -
+
@@ -31,41 +31,34 @@
+ +{% assign featured_services = site.data.featured_services %} +{% assign projects_list = site | find_collection: 'services_projects' | weighted_sort: 'project_weight', 'title' %} +
-
+

Case studies

    - {% assign featured_services = site.data.featured_services %} - {% assign projects_list = site | find_collection: 'services_projects' | weighted_sort: 'project_weight', 'title' %} - {% for featured in featured_services %} - {% assign featured_project = projects_list | where: "agency", featured.agency | first %} -
  • - {% include "card-project.html" project=featured_project.slug %} -
  • - {% endfor %} + {% for featured in featured_services %} + {% assign featured_project = projects_list | where: "agency", featured.agency | first %} +
  • + {% include "card-project.html" project: featured_project.slug %} +
  • + {% endfor %}
- {%- comment -%} -

- - See all case studies - {% include svg/icons/arrow-right.svg %} - -

- {%- endcomment -%} - -{% include "testimonial.html" - quote="18F’s philosophy to build everything openly by default has been a key success factor in our ability to build credibility with the external stakeholders who have been critical of us previously. More importantly, this way of building facilitates innovation in an eco-centric manner as opposed to just within the government or a few entities." - attribution="Christina Ho" - position="Former Deputy Assistant Secretary" - organization="Office of Accounting Policy & Financial Transparency, Department of the Treasury" - agency_image="treasury.svg" +{% include "testimonial.html", + quote: "18F’s philosophy to build everything openly by default has been a key success factor in our ability to build credibility with the external stakeholders who have been critical of us previously. More importantly, this way of building facilitates innovation in an eco-centric manner as opposed to just within the government or a few entities.", + attribution: "Christina Ho", + position: "Former Deputy Assistant Secretary", + organization: "Office of Accounting Policy & Financial Transparency, Department of the Treasury", + agency_image: "treasury.svg" %}
@@ -95,4 +88,3 @@

Some agencies we’ve worked with

- diff --git a/content/pages/press.html b/content/pages/press.html index f8c689ebf..1679040a9 100644 --- a/content/pages/press.html +++ b/content/pages/press.html @@ -3,48 +3,53 @@ permalink: /press/ redirect_to: /about/#for-press --- -

18F is a growing group of technologists, designers, and researchers from around the country who are committed to making government services simpler and easier to use. We put the needs of the American people first, we work in the open to make our products stronger, and we are design-centric, agile, open, and data-driven.

"If you have questions, we've got answers."

media@gsa.gov

What 18F has accomplished

-

MyUSCIS

-

A screenshot of the MyUSCIS homepage.

+

A screenshot of the MyUSCIS homepage.

We helped the U.S. Citizenship and Immigration Services (USCIS) launch myUSCIS, a platform that allows users to easily access information about the immigration process and find immigration options for which they may qualify. Re-imagining the immigration process meant moving from a form-centric website to a human-centric one. We worked closely with USCIS across multiple disciplines to create a suite of resources and tools to demystify the naturalization process, move application forms online, and design an improved account system for applicants.

+

BetaFEC

-

A screenshot of the betaFEC homepage

+

A screenshot of the betaFEC homepage

The Federal Election Commission (FEC) has long been a pioneer of open data, but 18F was able to help the FEC build its first public API and a new website on top of that API. This site helps make campaign finance information more accessible to the public, as part of a larger redesign of the FEC’s online presence. Read more about the site and why we’ve released it as a beta.

College Scorecard

-

A screenshot of the college scorecard

+

A screenshot of the college scorecard

The College Scorecard site is an example of what 18F can do to help your agency provide an interactive, well-designed way for the public to access your data. We worked with the U.S. Digital Service and the Department of Education to build College Scorecard to give students and their families access to previously unreleased data about colleges and universities so they can make better decisions. The site is built on top of a public API, which also allows private individuals and companies to use the data. Read more about the College Scorecard project.

+

U.S. Web Design System

-

A screenshot of standards.usa.gov

+

A screenshot of standards.usa.gov

In collaboration with the U.S. Digital Service, we created a collection of design patterns and user interface toolkits to help agencies focus on building their website or application without reinventing trustable, accessible solutions to common government problems. The Design System includes typography and color recommendations that are compliant with Section 508 of the Rehabilitation Act (the federal standard for accessibility), as well as a collection of foundational interface elements for government sites and the code that powers them. We have blogged about our work on the Design Systems several times.

+

analytics.usa.gov

-

A screenshot of the analytics.usa.gov homepage.

+

A screenshot of the analytics.usa.gov homepage.

You can now view a dashboard of analytics data from the websites of agencies participating in GSA's Digital Analytics Program. The basic dashboard has three views: one showing how many people are on government websites right now; the other two show the most popular pages on government sites in the last seven and 30 days. In 2016, we added agency-specific pages to the dashboard, allowing users to see the same data for several departments as well as across the entire government. This open source project has been adapted for use in other city and state governments.

+

cloud.gov

-

A screenshot of the cloud.gov homepage

+

A screenshot of the cloud.gov homepage

cloud.gov includes a Platform-as-a-Service (PaaS) specifically built for government, based on the open source Cloud Foundry. It provides a secure, scalable platform for teams to build and host their application or website. It can help development teams work faster and cheaper by handling much of their deployment complexity. The cloud.gov platform is currently in a small pilot program, but we will be expanding access over time.

+

Wage and Hour Division Field Operations Handbook

-

The 18F team working with Department of Labor staff in the GSA headquarters.

+

The 18F team working with Department of Labor staff in the GSA headquarters.

In two days, our consulting team was able to work with a team at the Department of Labor’s Wage and Hour Division to take the four-volume, printed Field Operations Handbook and create an internal prototype of an online, searchable version. We were also able to demonstrate the power of using agile design and development methods.

+

RFP Ghostwriting with the State of California

-

The California, Code for America, and 18F team after the workshop.

+

The California, Code for America, and 18F team after the workshop.

We partnered with the Department of Health and Human Services, the State of California, and Code for America to draft a request for proposal (RFP) to fix the state's child welfare case management system. This system is used by more than 20,000 social workers to track and manage the more than 500,000 cases of child abuse and neglect that are reported in California each year. 18F's two-day RFP ghostwriting workshop got stakeholders on board with modular contracting and modern development methodologies, and helped the state trim their initial 1,500 page RFP into two 70-page documents.

+

Every Kid in a Park

In collaboration with the U.S. Department of the Interior, The White House, and other federal agencies, 18F built a website to help U.S. fourth graders obtain their free pass to national lands and waters. The site is specially designed to be used by kids (its primary users).

+

U.S. Extractive Industries Transparency Initiative (U.S. EITI)

After holding a design studio for the Department of the Interior's Office of Natural Resource Revenues, 18F was able to build the first iteration of the U.S. implementation of a global project to bring transparency into natural resource management and the money paid to the government on public land leased to private companies. In preparation for Interior's first EITI report, the team continued to iterate and test their product with users across the United States. We've written about this project several times on the 18F blog.

+

CALC and Discovery

In two of our first projects, 18F worked with Federal Acquisition Service employees to create market research tools to help write better contracts and find better vendors to include in blanket purchase agreements. In addition to GSA contracting officers, CALC is also being used by the City of Boston.

-

18F projects adapted by other organizations

-

We publish our code repositories on GitHub and encourage the public to adapt our code and guides for their own projects.

Here are some examples of how our projects have been adapted by others:

-

18F's relationship with the U.S. Digital Service

-

18F and the U.S. Digital Service are distinct groups working toward the same vision of better digital government. 18F is a digital consultancy in an independent agency (GSA) and provides products and services to federal entities on a fee-for-service basis. The U.S. Digital Service is part of the Executive Office of the President and the United States CIO, supporting and coordinating the work of various digital service teams housed in agencies across the federal government.

-

Basic information on 18F’s history

-

    -
  • -

    GSA launched 18F on March 19, 2014. The name is an abbreviation for GSA’s address — 1800 F St.

    -
  • -
  • -

    The 18F team started with 15 full time staff. Staffing has grown to over 180 as of May 2016, as 18F’s product and client work has increased.

    -
  • -
  • -

    Our goal was (and is) to transform the way the U.S. government approaches problems. Read more about our evolution in the blog posts from our first and second anniversaries.

    -
  • +
  • GSA launched 18F on March 19, 2014. The name is an abbreviation for GSA’s address — 1800 F St.
  • +
  • The 18F team started with 15 full time staff. Staffing has grown to over 180 as of May 2016, as 18F’s product and client work has increased.
  • +
  • Our goal was (and is) to transform the way the U.S. government approaches problems. Read more about our evolution in the blog posts from our first and second anniversaries.
-

How 18F Works

-

18F works in partnership with agencies across government on a reimbursable basis. We deliver public-facing services via web applications, data and service Application Programming Interfaces (APIs), and platforms. 18F operates using three basic models:

  • For you: Building solutions for an agency
  • -
  • With you: Integrating with an agency team to provide additional expertise or core capacity
  • +
  • With you: Integrating with an agency team to provide additional expertise or core capacity
  • By you: Advising an agency on how to build or buy user-centric digital services most effectively

18F is an open source team. It uses open source development to transparently promote the security, quality, and modularity of our code and to invite review, participation, and free and simple reuse of our efforts by government agencies, the business community, and the public.

-

How 18F is funded

-

18F charges clients on a break even basis for the services we deliver. Revenue generated from these charges is held in the Acquisition Services Fund where it is made available for current and future operating expenses.

-

diff --git a/content/pages/principles/index.md b/content/pages/principles/index.md index 039b7e6df..d25166e86 100644 --- a/content/pages/principles/index.md +++ b/content/pages/principles/index.md @@ -28,7 +28,7 @@ The first thing you may notice when partnering with 18F is that your team will b In this document, we’ll explain each idea and how it will influence our work together. -[Download a PDF version of the Principles here]({{site.baseurl}}/partnership-principles/18FPartnershipPrinciples.pdf) +[Download a PDF version of the Principles here]({{site.baseurl}}/assets/presentations/18FPartnershipPrinciples.pdf) # Methodologies diff --git a/content/pages/projects/services/_services_projects/alaska-dhss.md b/content/pages/projects/services/alaska-dhss.md similarity index 100% rename from content/pages/projects/services/_services_projects/alaska-dhss.md rename to content/pages/projects/services/alaska-dhss.md diff --git a/content/pages/projects/services/_services_projects/c2.md b/content/pages/projects/services/c2.md similarity index 100% rename from content/pages/projects/services/_services_projects/c2.md rename to content/pages/projects/services/c2.md diff --git a/content/pages/projects/services/_services_projects/calc.md b/content/pages/projects/services/calc.md similarity index 100% rename from content/pages/projects/services/_services_projects/calc.md rename to content/pages/projects/services/calc.md diff --git a/content/pages/projects/services/_services_projects/dhs-myuscis.md b/content/pages/projects/services/dhs-myuscis.md similarity index 100% rename from content/pages/projects/services/_services_projects/dhs-myuscis.md rename to content/pages/projects/services/dhs-myuscis.md diff --git a/content/pages/projects/services/_services_projects/dod-military-onesource.md b/content/pages/projects/services/dod-military-onesource.md similarity index 100% rename from content/pages/projects/services/_services_projects/dod-military-onesource.md rename to content/pages/projects/services/dod-military-onesource.md diff --git a/content/pages/projects/services/_services_projects/doi-every-kid-in-a-park.md b/content/pages/projects/services/doi-every-kid-in-a-park.md similarity index 100% rename from content/pages/projects/services/_services_projects/doi-every-kid-in-a-park.md rename to content/pages/projects/services/doi-every-kid-in-a-park.md diff --git a/content/pages/projects/services/_services_projects/doi-nrrd.md b/content/pages/projects/services/doi-nrrd.md similarity index 100% rename from content/pages/projects/services/_services_projects/doi-nrrd.md rename to content/pages/projects/services/doi-nrrd.md diff --git a/content/pages/projects/services/_services_projects/doj-crt-portal.md b/content/pages/projects/services/doj-crt-portal.md similarity index 100% rename from content/pages/projects/services/_services_projects/doj-crt-portal.md rename to content/pages/projects/services/doj-crt-portal.md diff --git a/content/pages/projects/services/_services_projects/dol-wage-and-hour.md b/content/pages/projects/services/dol-wage-and-hour.md similarity index 100% rename from content/pages/projects/services/_services_projects/dol-wage-and-hour.md rename to content/pages/projects/services/dol-wage-and-hour.md diff --git a/content/pages/projects/services/_services_projects/ed-college-scorecard.md b/content/pages/projects/services/ed-college-scorecard.md similarity index 100% rename from content/pages/projects/services/_services_projects/ed-college-scorecard.md rename to content/pages/projects/services/ed-college-scorecard.md diff --git a/content/pages/projects/services/_services_projects/fbi-crime-data-explorer.md b/content/pages/projects/services/fbi-crime-data-explorer.md similarity index 100% rename from content/pages/projects/services/_services_projects/fbi-crime-data-explorer.md rename to content/pages/projects/services/fbi-crime-data-explorer.md diff --git a/content/pages/projects/services/_services_projects/fec-gov.md b/content/pages/projects/services/fec-gov.md similarity index 100% rename from content/pages/projects/services/_services_projects/fec-gov.md rename to content/pages/projects/services/fec-gov.md diff --git a/content/pages/projects/services/_services_projects/forest-service.md b/content/pages/projects/services/forest-service.md similarity index 100% rename from content/pages/projects/services/_services_projects/forest-service.md rename to content/pages/projects/services/forest-service.md diff --git a/content/pages/projects/services/_services_projects/hhs-states.md b/content/pages/projects/services/hhs-states.md similarity index 100% rename from content/pages/projects/services/_services_projects/hhs-states.md rename to content/pages/projects/services/hhs-states.md diff --git a/content/pages/projects/services/_services_projects/navy-reserve.md b/content/pages/projects/services/navy-reserve.md similarity index 100% rename from content/pages/projects/services/_services_projects/navy-reserve.md rename to content/pages/projects/services/navy-reserve.md diff --git a/content/pages/projects/services/_services_projects/nsf-brand-principles-project-page.md b/content/pages/projects/services/nsf-brand-principles-project-page.md similarity index 100% rename from content/pages/projects/services/_services_projects/nsf-brand-principles-project-page.md rename to content/pages/projects/services/nsf-brand-principles-project-page.md diff --git a/content/pages/projects/services/_services_projects/nsf-seedfund.md b/content/pages/projects/services/nsf-seedfund.md similarity index 100% rename from content/pages/projects/services/_services_projects/nsf-seedfund.md rename to content/pages/projects/services/nsf-seedfund.md diff --git a/content/pages/projects/services/_services_projects/state-uskpa.md b/content/pages/projects/services/state-uskpa.md similarity index 100% rename from content/pages/projects/services/_services_projects/state-uskpa.md rename to content/pages/projects/services/state-uskpa.md diff --git a/content/pages/projects/services/_services_projects/tax-court.md b/content/pages/projects/services/tax-court.md similarity index 100% rename from content/pages/projects/services/_services_projects/tax-court.md rename to content/pages/projects/services/tax-court.md diff --git a/content/pages/projects/services/_services_projects/treasury-data-act.md b/content/pages/projects/services/treasury-data-act.md similarity index 100% rename from content/pages/projects/services/_services_projects/treasury-data-act.md rename to content/pages/projects/services/treasury-data-act.md diff --git a/content/pages/projects/services/_services_projects/treasury-new-ten.md b/content/pages/projects/services/treasury-new-ten.md similarity index 100% rename from content/pages/projects/services/_services_projects/treasury-new-ten.md rename to content/pages/projects/services/treasury-new-ten.md diff --git a/content/pages/projects/services/_services_projects/us-web-design-standards.md b/content/pages/projects/services/us-web-design-standards.md similarity index 100% rename from content/pages/projects/services/_services_projects/us-web-design-standards.md rename to content/pages/projects/services/us-web-design-standards.md diff --git a/content/pages/work-with-us.md b/content/pages/work-with-us.html similarity index 85% rename from content/pages/work-with-us.md rename to content/pages/work-with-us.html index 93bc1a6e6..bd8f7e720 100644 --- a/content/pages/work-with-us.md +++ b/content/pages/work-with-us.html @@ -19,7 +19,7 @@ - Make your website work for you - Design processes to implement mandates and initiatives - Find the right vendor to set you up for long-term success -- [Create AI service strategies]({{ site.baseurl }}/AI-services) +- [Create AI service strategies]({{ site.baseurl }}/AI-services/) In each engagement, we take the time to understand your mission and the challenges you confront. Then, we draw from our deep well of technical expertise to create practical solutions to deliver the best outcomes for you and the people you serve. @@ -59,7 +59,7 @@

Transform the way you work

- {{ intro | markdownify}} + {{ intro | markdownify }}
@@ -97,20 +97,20 @@

Feel empowered to continue with our guides

We want agencies to be able to do the work themselves. Here are some free guides that help.

- {% include "card-with-image.html" - card_color="dark" - image_path="/assets/img/guides/state-guide-lightest.svg" - link_url="https://derisking-guide.18f.gov/state-field-guide/" - text_content="State Software Budgeting Handbook" + {% include "card-with-image.html", + card_color: "dark", + image_path: "/assets/img/guides/state-guide-lightest.svg", + link_url: "https://derisking-guide.18f.gov/state-field-guide/", + text_content: "State Software Budgeting Handbook" %}
- {% include "card-with-image.html" - card_color="dark" - image_path="/assets/img/guides/federal-guide-lightest.svg" - link_url="https://derisking-guide.18f.gov/federal-field-guide/" - text_content="Federal Field Guide" + {% include "card-with-image.html", + card_color: "dark", + image_path: "/assets/img/guides/federal-guide-lightest.svg", + link_url: "https://derisking-guide.18f.gov/federal-field-guide/", + text_content: "Federal Field Guide" %}
@@ -136,16 +136,16 @@

Read related case studies

{% assign projects = 'fec-gov, treasury-data-act' | split: ", " %} {% for project in projects %} - {% assign project_details = site | find_collection: 'services_projects' | where: 'slug', project | first %} - {% assign project_agency = site.data.agencies | where: "name", project_details.agency | first %} - {% assign project_link = site.baseurl | append: project_details.permalink %} + {% assign project_details = collections.service | where: 'fileSlug', project | first %} + {% assign project_agency = project_details.data.agencies | where: "name", project_details.data.agency | first %} + {% assign project_link = site.baseurl | append: project_details.data.permalink %}
- {% include "card-with-image.html" - image_path=project_agency.logo - image_alt_text=project_agency.name - image_size="md" - link_url= project_link - text_content=project_details.mini_excerpt + {% include "card-with-image.html", + image_path: project_agency.logo, + image_alt_text: project_agency.name, + image_size: "md", + link_url: project_link, + text_content: project_details.data.mini_excerpt %}
{% endfor %} diff --git a/content/posts/2014-03-19-hello-world-we-are-18f.md b/content/posts/2014-03-19-hello-world-we-are-18f.md index 5beca49f1..c9833adc6 100644 --- a/content/posts/2014-03-19-hello-world-we-are-18f.md +++ b/content/posts/2014-03-19-hello-world-we-are-18f.md @@ -95,4 +95,4 @@ agile manner is possible in government at scale. [Let us know]({{ site.baseurl }}/contact/) how we can help you, and how you can help us (hint: we want you!). -[Team 18F]({{ site.baseurl }}/about) +[Team 18F]({{ site.baseurl }}/about/) diff --git a/content/posts/2014-10-01-open-source-hack-series-midas.md b/content/posts/2014-10-01-open-source-hack-series-midas.md index c3790ed4f..26d5e1647 100644 --- a/content/posts/2014-10-01-open-source-hack-series-midas.md +++ b/content/posts/2014-10-01-open-source-hack-series-midas.md @@ -31,7 +31,7 @@ tags: ## What is Midas? -[Midas is an online marketplace of skill building opportunities]({{site.baseurl}}/2014/07/16/midas-a-marketplace-for-innovation-in-government) which matches people to projects that they’re passionate about. Our goal is to foster innovation across team boundaries by connecting projects or challenges that need help within federal government agencies to people who want to work collaboratively on the solution. +[Midas is an online marketplace of skill building opportunities]({{site.baseurl}}/2014/07/16/midas-a-marketplace-for-innovation-in-government/) which matches people to projects that they’re passionate about. Our goal is to foster innovation across team boundaries by connecting projects or challenges that need help within federal government agencies to people who want to work collaboratively on the solution. "It's like a Kickstarter for people's time." –Joe Polastre at [18F Demo Day](https://speakerdeck.com/18f/innovation-toolkit-18f-demo-day-9-may-2014?slide=3) diff --git a/content/posts/2014-12-22-protosketch.md b/content/posts/2014-12-22-protosketch.md index 8ffe2b27c..5bce2ac79 100644 --- a/content/posts/2014-12-22-protosketch.md +++ b/content/posts/2014-12-22-protosketch.md @@ -42,7 +42,7 @@ Every agency deserves this ability to realize its mission more effectively and t ## De-risking the procurement process -In a typical procurement setting, prospective contractors might be the most technical voices in the room, creating a risk of technical asymmetry. A protosketcher, whether they are from [18F Consulting]({{ site.baseurl }}/consulting) or from within the agency, should act as a trusted technical adviser to the program manager. A meeting with a protosketcher will significantly mitigate any asymmetry in technical expertise between the agency and prospective contractors by demonstrating technical possibilities and the ease of various solutions. The program manager will better understand what they want to get out of an RFP and be empowered to write on based on a more certain understanding of the problem and possible solutions. Contractors will find this specificity and clarity refreshing and produce lower, more accurate bids. The American people will be rewarded with less vendor lock-in, more cost effective maintenance, and effectively evolving digital services. Oh and better digital experiences! +In a typical procurement setting, prospective contractors might be the most technical voices in the room, creating a risk of technical asymmetry. A protosketcher, whether they are from 18F Consulting or from within the agency, should act as a trusted technical adviser to the program manager. A meeting with a protosketcher will significantly mitigate any asymmetry in technical expertise between the agency and prospective contractors by demonstrating technical possibilities and the ease of various solutions. The program manager will better understand what they want to get out of an RFP and be empowered to write on based on a more certain understanding of the problem and possible solutions. Contractors will find this specificity and clarity refreshing and produce lower, more accurate bids. The American people will be rewarded with less vendor lock-in, more cost effective maintenance, and effectively evolving digital services. Oh and better digital experiences! ## Protosketching in the wild: actual experience diff --git a/content/posts/2015-04-24-agile-developments-secret-weapon-transparency.md b/content/posts/2015-04-24-agile-developments-secret-weapon-transparency.md index 63dcdc313..fbb88be0a 100644 --- a/content/posts/2015-04-24-agile-developments-secret-weapon-transparency.md +++ b/content/posts/2015-04-24-agile-developments-secret-weapon-transparency.md @@ -13,7 +13,7 @@ tags: excerpt: "18F Consulting recommends agile development for several reasons, including agile’s emphasis on user needs, continuous integration, and rapid adaptation to changed circumstances. But there is another important reason we recommend agile: its focus on transparency." description: "18F Consulting recommends agile development for several reasons, including agile’s emphasis on user needs, continuous integration, and rapid adaptation to changed circumstances. But there is another important reason we recommend agile: its focus on transparency." --- -[18F Consulting]({{ site.baseurl }}/consulting) recommends agile +18F Consulting recommends agile development for several reasons, including agile’s emphasis on user needs, continuous integration, and rapid adaptation to changed circumstances. But there is another important reason we recommend agile: diff --git a/content/posts/2017-01-04-tracking-the-us-governments-progress-on-moving-https.md b/content/posts/2017-01-04-tracking-the-us-governments-progress-on-moving-https.md index 2597bfc07..d794fc652 100644 --- a/content/posts/2017-01-04-tracking-the-us-governments-progress-on-moving-https.md +++ b/content/posts/2017-01-04-tracking-the-us-governments-progress-on-moving-https.md @@ -26,7 +26,7 @@ There's more detail and caveats below — and in particular, this focuses only o * The White House policy generated significant HTTPS adoption in the U.S. government, to the point that **[the government now outpaces the private sector on HTTPS](#did-we-need-a-formal-https-policy)**. * HTTPS has gone from **[a clear minority to a clear majority](#evaluating-adoption)** of support across executive branch .gov domains since the release of the policy. -* Web traffic data suggests that **[HTTPS is now used for most web requests](#measuring-overall-user-impact-using-analyticsusagov)** to executive branch .gov web services. +* Web traffic data suggests that **[HTTPS is now used for most web requests](#measuring-overall-user-impact-using-analytics-usa-gov)** to executive branch .gov web services. * In 2017, agencies should focus on closing gaps through the use of **[inexpensive and free certificates](#recommendations-and-data)**, and by **[preloading their domains](#recommendations-and-data)** wherever possible. ## Measuring .gov domains and subdomains diff --git a/content/posts/2019-12-3-long-term-teams.md b/content/posts/2019-12-3-long-term-teams.md index 8a341cd24..c14febdcb 100644 --- a/content/posts/2019-12-3-long-term-teams.md +++ b/content/posts/2019-12-3-long-term-teams.md @@ -26,7 +26,7 @@ Although this is a common approach, it is a very risky one, because: 1. Handing off software to a completely new team squanders hard-won knowledge. 2. Handoff to operations & maintenance brings a "keep the lights on" mindset, rather than planning for active continuous delivery. -Former Presidential Innovation Fellow [Sarah Allen]({{site.baseurl}}/author/sarah) wrote about this topic in 2016 in her fantastic post, "[Software maintenance is an anti-pattern](https://18f.gsa.gov/2016/02/23/software-maintenance-is-an-anti-pattern/)." (We hope you will give Sarah's post a read if you haven't come across it before!) In this post, we want to build on Sarah's arguments about software maintenance anti-patterns. +Former Presidential Innovation Fellow {{ "sarah" | team_link }} wrote about this topic in 2016 in her fantastic post, "[Software maintenance is an anti-pattern](https://18f.gsa.gov/2016/02/23/software-maintenance-is-an-anti-pattern/)." (We hope you will give Sarah's post a read if you haven't come across it before!) In this post, we want to build on Sarah's arguments about software maintenance anti-patterns. If you find your agency planning an abrupt handover to O&M after a software launch, we hope this post will provide you with reasoning and examples to support a different approach: building a technical team for the long term. @@ -70,7 +70,7 @@ How are they building out a team to carry the work forward, one slice of product The Open Forest effort explored potential partnerships with other internal government IT services before settling on their partnership with the Forest Service ACIO, making sure the two agencies shared the same product goals and technical directions. -"There is amazing talent within the Forest Service. Our Forest Service partners identified people with subject matter expertise to work alongside us and deepen their knowledge and experience with iterative software development. Those folks are now continuing to develop the product on their own, further embedding this way of working within the organization," said [Melissa Braxton]({{site.baseurl}}/author/melissa-braxton), former 18F design and product lead on Open Forest. +"There is amazing talent within the Forest Service. Our Forest Service partners identified people with subject matter expertise to work alongside us and deepen their knowledge and experience with iterative software development. Those folks are now continuing to develop the product on their own, further embedding this way of working within the organization," said {{ "melissa-braxton" | team_link }}, former 18F design and product lead on Open Forest. What advice does Aaron have for other agencies embarking on a similar agile journey? "Choose a low-risk option to build your pilot. We didn't choose a complex permitting process to start. Starting small mitigates risk as you develop new services, and allows you to identify capability and skill gaps." diff --git a/package.json b/package.json index 389f40b50..723484a84 100644 --- a/package.json +++ b/package.json @@ -31,24 +31,14 @@ "author": "", "license": "CC0-1.0", "devDependencies": { - "@11ty/eleventy": "^2.0.1", - "@11ty/eleventy-navigation": "^0.3.5", - "@11ty/eleventy-plugin-rss": "^1.2.0", - "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", "chai": "^4.4.1", "check-html-links": "^0.2.4", "chokidar-cli": "^3.0.0", - "csv-parse": "^5.5.6", - "eleventy-plugin-svg-sprite": "^1.3.1", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", "html-validate": "^8.18.2", - "js-yaml": "^4.1.0", "jsdom": "^22.1.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.6.7", - "markdown-it-attrs": "^4.1.6", "mocha": "^10.4.0", "netlify-cms": "^2.8.0", "netlify-cms-proxy-server": "^1.3.23", @@ -61,12 +51,22 @@ "start-server-and-test": "^2.0.3" }, "dependencies": { + "@11ty/eleventy": "^2.0.1", + "@11ty/eleventy-navigation": "^0.3.5", + "@11ty/eleventy-plugin-rss": "^1.2.0", + "eleventy-plugin-svg-sprite": "^1.3.1", + "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", "@11ty/eleventy-img": "^3.1.8", "@uswds/uswds": "3.8.0", "autoprefixer": "^10.4.19", + "csv-parse": "^5.5.6", "esbuild": "^0.20.2", "esbuild-sass-plugin": "^3.2.0", + "js-yaml": "^4.1.0", "luxon": "^2.3.1", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.6.7", + "markdown-it-attrs": "^4.1.6", "markdown-it-footnote": "^3.0.3", "netlify-cms": "^2.10.192" },