Skip to content

nyc-cto/ds-ws-lpaas2

Repository files navigation

NYC MOCTO Landing Page as a Service 2.0

Requirements

  1. Operating System: macOS Sierra (10.12) or later, Windows 10, or Linux.
  2. Node.js 10.13.0 (LTS) or higher.
  3. A code editor, such as Visual Studio Code.
  4. Git version control system.
  5. npm package manager.
  6. Gatsby command line interface (CLI).
  7. A GitHub account.
  8. A Microsoft Azure account (if deploying with Azure).

Getting Started

  1. Click the Use this template button.
  2. Select a name for your new repository.
  3. Click Create repository from template.
  4. Click the Code button to clone the repository and follow instructions to clone to your local machine.
  5. Navigate to the directory on your local machine.
  6. Install dependencies with npm install.
  7. Add env.development file to the root directory of your project. This file should follow the structure of the /.env.template file. Fill in your secrets.
  8. Run the Gatsby development server gatsby develop or npm run dev.

Project Structure

Files & Folders You Should Edit

  1. .github. If you deploy with Azure, you will generate your own .github/workflows/azure-static-web-apps-<RANDOM_NAME>.yml file.
  2. src/constants. You can edit the files in this folder to update links and add additional language support.
  3. src/images. Edit contents in this folder to update the agency logos, background image used in the hero, or the images in the graphics section. See Changing Images.
  4. src/locales. This folder contains folders for each language used and corresponding translation.json files. These translation files include the text for elements that are included in every page of the webapp, such as the header, footer, navigation bar, and language selector module.
  5. src/markdown-pages. This folder contains folders that correspond to each template page. Within each of those folders (ex. documentation or landing) there are markdown files that include the content of the specific template page, and each markdown file represents a different language. These are the files you will change to customize the text in the body of each page to fit your specific project and to provide translations of the content.
  6. src/styles/_custom-theme.scss. You can edit this file to customize the theme of the webapp, including changing the color scheme and font. See Customizing the Theme. README.md. You can update this file to provide information about your project.

Files & Folders You Should Not Need to Edit

  1. /public. This folder is automatically generated by Gatsby.
  2. src/components.
  3. src/pages.
  4. src/styles/. Do not edit any files except for src/styles/_custom-theme.scss.
  5. src/templates. Do not edit existing templates.
  6. .eslintrc.
  7. .gitignore.
  8. gatsby-browser.js, gatsby-config.js, or gatsby-node.js.
  9. LICENSE.md.
  10. package-lock.json or package.json.

Styling

Customizing the Theme

To update the theme, you only need to edit src/styles/_custom-theme.scss. In this file, edit the values assigned to variables that begin with $custom-.

If you feel the need to customize the theme even further, you can use the variables from USWDS that begin with $theme- in src/styles/_custom-theme.scss. You can read more about USWDS theme variables here.

Changing Images

Hero Background Image

  1. The hero background image is set in src/styles/_custom-theme.scss, as follows $custom-hero-image: '../images/hero.png'.
  2. To update the hero background image either replace src/images/hero.png with a file of the same name and extension or add a new image file and update the file path name assigned to the variable $custom-hero-image.

Logos

  1. Replace the files in src/images/logos.
  2. If you replace the images with files of the same names and extensions then no other changes are needed. Replacing the logo image files with files of the same names and extensions is recommended.
  3. If you replace the images with files of different names or extensions, you will need to edit the exports in src/images/index.js. In this case, only change the path name, not the variable name of the exported image.

Graphics Section Images

  1. Replace the files in src/images/graphics.
  2. If you replace the images with files of the same names and extensions then no other changes are needed. Replacing the graphics image files with files of the same names and extensions is recommended.
  3. If you replace the images with files of different names or extensions, you will need to edit the imports in src/images/index.js. In this case, only change the path name, not the variable name.

Content

Editing Content

The content that is unique to a specific page (ex. documentation or landing) is stored in markdown files (src/markdown-pages/documentation or src/markdown-pages/landing).

  1. If the content is in the front matter of the markdown file (if it is in between the three dashes ---) only edit the text after the colon. The front matter follows YAML syntax. For instance, you can edit the text “Everything up to this point…”, but you should not edit section:, heading, or text. Also, do not edit the indents already in the front matter.
section:
  heading: Section heading
  text: Everything up to this point should help people understand your agency or project who you are, your goal or mission, and how you approach it.
  1. If the content is below the three dashes, it uses markdown syntax.

Templates

Adding a New Template Page

  1. Create a new .jsx file in src/templates/.
  2. Create corresponding markdown files for this template page as shown in src/documentation/ and src/landing/.
  3. In the front matter of the new markdown files, include: lang, templateKey, slug, and pageTitle. These represent the language of the page (language code), the template being used in src/templates (file name), the path for this page (shown in the address bar), and the title of the page, respectively.
---
lang: en
templateKey: documentation-page
slug: documentation
pageTitle: Project | Documentation
---
  1. In your newly created .jsx file from step one, do the following: Create a new component (we recommend using a functional component) and export it by default.
import React from 'react';
function NewTemplatePage() {}
export default NewTemplatePage;
  1. Import the layout component src/components/layout.jsx. This includes the header, navigation, language selection, and footer. You must use this to make sure navigation takes place effectively from your page to other pages.
import { Layout } from '../components';
function NewTemplatePage() {
  return <Layout>{/* your stuff inside layout */}</Layout>;
}
export default NewTemplatePage;
  1. Import GraphQL from Gatsby. Write a GraphQL query to get content from markdown files. See Gatsby’s GraphQL Concepts for more information or check out existing templates.
import { graphql } from 'gatsby';
  1. Include data as a prop in your template component. Using the following syntax, you will be able to access the elements of the front matter and markdown body:
const { markdownRemark } = data;
const { frontmatter, html } = markdownRemark;

You can access front matter elements as properties of the frontmatter object, using object dot notation as follows: frontmatter.pageTitle.

In the template’s JSX, you can set the HTML as follows: <div dangerouslySetInnerHTML={{ __html: html }}/>. Include pageContext as a prop as well and use the following syntax to access the languageList, which is an array of all the languages used in the src/locales folder:

const { languageList } = pageContext;
  1. Import useTranslation from i18next.
import { useTranslation } from 'react-i18next';
  1. Within the component use the following syntax to access the i18n object:
const { i18n } = useTranslation();
  1. Use React Helmet to set the page title and language:
import { Helmet } from 'react-helmet';
import { useTranslation } from 'react-i18next';
function NewTemplatePage() {
  const { i18n } = useTranslation();
  return (
    <>
      <Helmet
        title={frontmatter.pageTitle}
        htmlAttributes={{ lang: i18n.language }}
      />
      <Layout>
        <main>
          {/* use main tags to indicate the main content */}
          {/* your code inside main */}
        </main>
      </Layout>
    </>
  );
}
  1. Import components from src/components/ as needed.
  2. Pass languageList and frontmatter.slug as props to the Layout component. You can also pass data from the front matter to other components as well. See the following example:
function NewTemplatePage() {
  const { i18n } = useTranslation();

  return (
    <>
      <Helmet
        title={frontmatter.pageTitle}
        htmlAttributes={{ lang: i18n.language }}
      />
      <Layout languageList={languageList} slug={frontmatter.slug}>
        <main>
          <h1>{frontmatter.heading}</h1>
          <p className="usa-intro">{frontmatter.prose}</p>
        </main>
      </Layout>
    </>
  );
}

Language Access & Internationalization

The src/locales folder contains folders for each language used, which are named according to their language code. Each of the language folders has a translation.json file, which contains the text for elements that are included in every page of the webapp, such as the header, footer, navigation bar, and language selector module.

The LPAAS 2.0 template already contains placeholder translation and markdown files for the 10 designated citywide languages under Local Law 30.

Adding a Language

  1. To add a new language, create a new folder in src/locales . The name of this folder should be the language code.
  2. Within the new folder, create a translation.json file.
  3. Copy and paste the JSON object from another translation file and replace all of the string values in the key-value pairs with the corresponding translations. Do not change any of the keys. In the following example, you can translate “Project Title”, but should not edit “title”.
{
  "title": "Project Title"
}
  1. In src/i18n-config.js, add the new language to resources. See the example below:
resources: {
 ar: {
   translations: require('./locales/ar/translation.json'),
 },
 bn: {
   translations: require('./locales/bn/translation.json'),
 },
//other language resources not shown for brevity
  1. If the language you are adding is not one of the designated citywide languages under Local Law 30 and is not already included in src/constants/languages.js, add the language name and language code as key value pairs of an object in the languages array, as follows:
{
  lang: 'English',
  langKey: 'en',
}
  1. In src/markdown-pages, create a new markdown file for each template in your new language. For instance, if you were adding pages in Spanish, you would need to create a new file in each folder (404, documentation, landing, and any additional folders). We recommend that each of the new files should be named the same thing as the folder, followed by a dash, and language code: src/markdown-pages/landing/landing-es.md and src/markdown-pages/documentation/documentation-es.md

Removing a Language

  1. To delete a language, delete the corresponding folder in src/locales and its contents.
  2. In src/i18n-config.js, delete the language from the resources object.
  3. In src/markdown-pages, delete the corresponding markdown file from each folder.

Links & Navigation

  1. Navigation links are stored in src/constants/links, while navigation labels are stored in the translation files in src/locales. The links in the navigation in the header are also shown in the footer for accessibility.

Editing Navigation Links

  1. To edit the link itself, simply change the desired path in src/constants/links.
  2. To edit the label of the link, update the text in all of the translation files in src/locales.

Adding Navigation Links

  1. Navigation links and labels are stored as key-value pairs. The label values are pulled from the translation files. Add the label using object property syntax and the link to src/constants/links.js. Internal links should not begin with a forward slash /. In the header, links can either be in navigation dropdown menus or standalone links (parent links). In the example below, the first array in navDropDowns will be included in one dropdown menu and the second array will be in another.
export const header = {
  navDropDowns: [
    // dropdowns
    // first dropdown start
    [
      {
        LABEL: 'navigation.dropdowns.0.linkLabels.0',
        LINK: 'link-one',
      },
      {
        LABEL: 'navigation.dropdowns.0.linkLabels.1',
        LINK: 'link-two',
      },
    ],
    // first dropdown end
    // second dropdown start
    [
      {
        LABEL: 'navigation.dropdowns.1.linkLabels.0',
        LINK: 'link-three',
      },
      {
        LABEL: 'navigation.dropdowns.1.linkLabels.1',
        LINK: 'link-four',
      },
    ],
    // second dropdown end
  ],
  parentLinks: [{ LABEL: 'navigation.parentLinkLabels.0', LINK: 'link-five' }], // parent (standalone) links
};

We suggest not having more than three links per dropdown menu and not having more than eight links in the dropdown menus and standalone links combined.

  1. Add the label for the link in each translation file in src/locales, corresponding to the label location in the previous step.

Deleting Navigation Links

  1. Delete the object associated with the link in src/constants/links.
  2. Delete the label in each translation file in src/locales. Be sure to complete this step, otherwise labels and links could be mismatched.

Editing Navigation Dropdown Menu

  1. To edit the label of the dropdown menu, update the text of buttonLabel in navigation.dropdowns in all of the translation files in src/locales.
  2. To edit the links and associated labels for the links in a dropdown menu, see Editing Navigation Links, Adding Navigation Links, or Deleting Navigation Links.

Adding Navigation Dropdown Menu

  1. Add a subarray to the header.navDropDowns array in src/constants/links.js. The elements of the subarray are objects with label and link keys.
  2. Each label will correspond to a linkLabel in the translation.json files.
  3. Add the corresponding link labels in the translation.json files in src/locales. In the translation files, each object in the navigation.dropdowns array corresponds to a dropdown menu. The buttonLabel is the label of the dropdown button. The linkLabels array contains the labels of all of the links listed in the dropdown menu. See the example below:
"navigation": {
  "dropdowns": [
    {
      "buttonLabel": "Nav Label 1",
      "linkLabels": ["Simple link one", "Simple link two"]
    }
  ]
}

Deleting Navigation Dropdown Menu

  1. Delete the desired subarray to the header.navDropDowns array in src/constants/links.js.
  2. Delete the desired element in the navigation.dropdowns array in every translation.json file.

Editing Button Links

  1. Button links are stored in src/constants/links.js and can be updated there.
  2. Button labels are stored in translation files if the buttons occur on every page and are stored in markdown files if the buttons are specific to a singular page.

Deployment

Deploying with Microsoft Azure Static Web Apps

To deploy your site using Azure, follow the Publish a Gatsby site to Azure Static Web Apps tutorial, starting at the Deploy your web app section.

Editing Application Settings Configuration

In order to set environment variables, follow the Configure application settings for Azure Static Web Apps tutorial. Enter the environment variables (application settings) for GATSBY_ENDPOINT and GATSBY_TITLE.

Editing GitHub Actions Workflow

To edit your site's GitHub Actions build workflow in .github/workflows, follow the GitHub Actions workflows for Azure Static Web Apps tutorial.

Creating a DNS Record in a Custom Domain

To create a DNS record, follow the Create DNS records in a custom domain for a web app tutorial.

Troubleshooting

If node_modules was not installed properly, you might have to run ​​npm install --legacy-peer-deps.

Thanks

The Mayor's Office of the CTO would like to thank Anya Dunaif (@aannyyaa), Saiful Islam (@saifulislamdev), and Britney Johnson for their significant contributions to this project as a summer CIC Fellow in 2021.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •