Table of contents
Clone this repo:
git clone https://github.com/clinicjs/clinicjs-site.git
Navigate into the directory and run the following:
cd clinicjs-website
npm install
npm run develop
You should now be able to see the website at http://localhost:8000 🙌
- Staging: clinicjs.netlify.com
- Live: clinicjs.org
Netlify is used to create staging environments using Deploy previews. Every time you create a pull request against main
you'll find a link to the preview under 'checks'. Find out more here. Technically the staging environment just mirrors live, so use deploy previews to check changes with a sharable URL when creating PRs.
The Netlify website is linked to the NearForm team account. Speak to Eamonn for access.
💡 To clear the ServiceWorker cache add ?no-cache=1
to the end of any URL when looking at changes.
The master
uses Github Actions to deploy to an AWS bucket automatically. Any PRs merged into master
The site is built with Gatsby 2 which is a static site generator that uses webpack and React and is enhanced using Remark to build content from markdown files.
npm run develop
Alias to run gatsby develop
which starts development env at http://localhost:8000
npm run build
Alias to run gatsby build
which builds static version of site in public
directory
npm run serve
Alias to run gatsby serve
which starts a static server to test built site.
npm run lint
This will run eslint in the /src
directory
npm run format
This will run prettier on all source JS (non-bundled) and on all markdown inside the /content
directory.
npm run write-good
This will flag any prose errors within the /content
directory.
npm run clean
If there's an unknown Gatsby error, chances are the /.cache
or /public
directory are out of whack. This is a convenience command for removing those directories.
There are two ways to create new pages, depending on the author's intent:
- Create an interactive page using React components. View
- Create page which is generated by markdown (via remark). View (recommended)
Gatsby core will automatically take all React components in src/pages
and turn them into pages. The name of the file will match the route of the component.
src/pages/test.js
would automatically load at http://localhost:8000/test
All markdown content is stored in the content/
directory. Any nested directory inside this content/
directory represents a "project" directory. This directory structure inside the content/
directory dictates the route of the post by subdirectory name or file name. To link a post to the subdirectory name itself use an index.md
file.
content/doctor/index.md => /doctor
content/doctor/tutorial/index.md => /doctor/tutorial
content/doctor/api.md => /doctor/api
content/doctor/tutorial/first-step.md => /doctor/tutorial/first-step
Markdown is parsed using Remark and used the GitHub syntax, so should be familiar if you are used to writing README.md
files or even PRs. Since markdown also supports HTML, you can add pure HTML to the markdown files, but for sanity this should be kept to an absolute minimum.
Simply use the markdown ![Alt tag](/image/path)
syntax where possible, although in some cases where you need to specify a size for the image you can use an <img>
tag.
Where GIFs are required you should simply use MP4 s if possible. This will be more performant, lightweight and easier to manage.
To place a GIF-like video in a markdown file use the following HTML with these boolean attributes to enable looping, remove controls and ensure it autoplays on page load without sound:
<video src="/path/to/video.mp4" playsinline loop autoplay muted></video>
To record your screen and create a video to place in a page you can follow the steps in the video here.
The steps are as follows:
- Record your screen with Nimbus Chrome extension
- Convert the saved WEBM as an MP4 with the Handbrake app and use the 'Web optimised' option when converting
- Place your MP4 file in an accessible folder a link to the relative path using the code snippet above.
💡 To convert the video as a GIF, use ezgif*.
This is not recommended, use an MP4 within the markdown for performance and quality reasons)
The dimensions of the videos used within the website currently are as follows:
Dimensions: 1440x798px
This ensures the video fits wide enough when full width on desktop and is a good size to present each Clinic.js tool to a user.
Dimensions: 1100×758px
This ensures the video fits wide-screen on desktops with good pixel density when scaled for retina screens and ensures a concise UI presentation across Clinic.js tools..
You might want to generate an image from a video for social media/meta data purposes. There are many ways to achieve this, but the most precise and quickest method would be to use ffmpeg
which is a CLI tool for converting and augmenting videos.
- Install using Homebrew:
brew install ffmpeg
- Generate a JPG from an MP4 at a timestamp as follows:
ffmpeg -i INPUT.mp4 -ss 00:00:00 -vframes 1 OUTPUT.jpg
This will generate an image of the first frame of the video in the same dimensions as the source video.
Code is syntax-highlighted using Prism. You should use language tags on the opening of the codeblock to ensure your code examples look pretty and are easy to read like so:
```js
const foo = () => 'bar'
```bash
npm install -g clinic
To add a fixed ID to any documentation page instead of relying on the ID automatically generated by the gatsby-remark-autolink-headers
plugin you can use this HTML:
<div id="controls-c" data-offset></div>
💡 Be sure to add empty lines above and below the above HTML within your Markdown
This is useful for when you might want to link to a part of the docs from an external website without risking the ID changing in the future.
Templates are used to to enhance the related markdown page and offer particular extended functionality based on the type of content and the frontmatter provided. Templates are associated with markdown content on build, so when developing it is important to restart the dev server to rebuild and re-link markdown content.
There are two methods by which content is displayed with a particular template:
Any content in a top level directory in the main /content
directory will be linked to a template of the same name in the /src/templates
directory.
/content/documentation/index.md => /src/templates/documentation.js
/content/documentation/doctor/index.md => /src/templates/documentation.js
/content/documentation/bubbleprof/01-setup.md => /src/templates/documentation.js
Should a piece of content not have a named template, the markdown will be displayed in the /src/templates/default.js
template.
Using frontmatter
it is possible to override the implicit linking by defining which template to use like so:
template: tool
Will link the content to the /src/templates/tool.js
template.
Frontmatter is used to add extra contextual information to the markdown page and is written as YAML
at the top of the file between ---
delimiters like so
---
# Frontmatter
key: Some string value...
---
# Here's an h1
And a paragraph....
Comments in the frontmatter YAML
are not parsed and so are recommended to help future and other content editors 👍
Building on the frontmatter data format, certain templates have enhanced functionality which rely on optional data passed to them.
All templates can take a metaData
object which is combined with the default meta data in the /data/meta-data.js
file and output using React Helmet in the /src/components/MetaData.js
component.
The frontmatter options are as follows:
metaData:
titleParts:
- Doctor
description: Diagnose performance issues in your Node.js applications
image: https://source.unsplash.com/random/800x450
Defines all parts of the title which will be prepended to the page <title />
and joined with a dash.
Will be used for the following meta tags:
<meta name="description" content="DESCRIPTION" />
<meta property="og:description" content="DESCRIPTION" />
<meta name="twitter:description" content="DESCRIPTION" />
Will be used for the following meta tag:
<meta property="og:image" content="DESCRIPTION" />
# Copy for the team section of the template
teamSectionTitle: The Clinic.js experts
# CTA button for bottom of template
cta:
label: Visit Clinic.js Github repo
path: https://github.com/clinicjs/node-clinic
Within the markdown itself, the following element will be replaced with the Team
component to show the NearForm team associated with Clinic.js:
<template data-team />
This is crudely replaced with a react component within the template and fed with data that's pulled from stub content in the /content/stubs/team
directory. This has been done to reduce the complexity of the frontmatter in the main 'About' markdown file and while it will create a page, it will not be visible unless linked to within the website.
Note the priority is used to control the order in which the team members appear in the Team
component in the generated page.
This template uses GraphQL to look for all converted markdown pages using a regex filter on the page path to ensure it is a blog post. This limits all blog posts to a fixed path canonical '/blog'. Each found page will display as a card which is powered by the frontmatter.
Each blog post markdown file has the following frontmatter support:
# Post author(s)
author: "Andreas Madsen"
# Post date [Y-M-D] (used for ordering)
date: "2018-08-22"
# Use this instead of an h1 in markdown
title: "Clinic.js Doctor just got more advanced with TensorFlow.js"
# The featured image in the blog post card where displayed
hero: "/assets/images/doctor-tensorflow.png"
The title
, date
and author
values are combined to create the post heading and all other content outside the frontmatter is parsed as HTML like other templates. Please ensure you don't use a markdown # h1
as this will repeat in the page.
This is a catch-all template and simply renders the markdown HTML with support for the metaData
frontmatter only.
This template is used for the documentation part of the website and is powered by the content in the subdirectories along with the content tree JSON.
This template displays any content which is explicitly linked using the template
frontmatter key.
The frontmatter options available are as follows:
# Ensure the content and frontmatter is passed to the correct template explicitly
template: tool
# Add context to the template (icon, colour etc)
type: doctor
# Ordering (lowest first)
priority: 1
# Heading 1
title: Clinic.js Doctor
# Subtitle (Heading 2)
subtitle: Diagnose performance issues in your Node.js applications
# List of tool features
features:
- Collects metrics by injecting probes
- Assess health and heuristics
- Creates recommendations
# Tool featured video for homepage
video: /assets/videos/doctor-feature.mp4
# Links for template buttons
gitHubUrl: https://github.com/clinicjs/node-clinic-doctor-examples
exampleUrl: static/assets/html/doctor-example.html
# CTA button for tool template
cta:
label: Get started with Doctor
path: /documentation/doctor/
This links content to the tool.js
template and ensures it is surfaced on the homepage in the index.js
React page.
This gives the necessary tool branding to the content with the relevant icon and colour scheme. Supported types are:
doctor
bubbleprof
flame
heapprofiler
Look at the /src/theme/helpers/tool-attributes.js
helper for more insight.
This is used in the /src/pages/index.js
page components GraphQL to show up to three tools on the homepage in an order chosen by the content editor.
The tool title which is combined in the template to show along with the buttons and icon to create the page heading or as part of the funnel on the homepage.
Subtitle on the page or as part of the funnel on the homepage.
Used only in the tool funnel on the homepage for the styled feature lists with arrows.
Used only in the tool funnel on the homepage as the promoted animation linking trough to the tool page.
Button URLs for the page heading
Used for the internal CTA button link and text to drive users to documentation for that tool
This is the homepage which is fed with tool, blog and testimonial content using GraphQL and the SiteConfig.js
file.
This is the Commercial Support page which is fed with support-package, testimonial and FAQ stub content using GraphQL and the SiteConfig.js
file.
fix/filenames Generic 404 handler. Necessary for in-browser redirects to work when the website is built statically. The copy for the heading and CTA are editable in the
SiteConfig.js
file.
Stubs live as normal markdown content in the /content/stubs
directory. A stub is a piece of parsed markdown which is non-indexable (due to sitemap.xml
exclusion rules) and is used to enhance templates and pages with extra content-editable features. As of writing, stubs only make use of frontmatter to provide content to components within the website.
Team member stubs are used to power the images, names and social media links in the 'The Clinic.js experts' section of the about page.
To update a team member, simply edit the frontmatter in their named markdown file. The options are as follows:
# Team member name
title: Matteo Collina
# Team member image
image: https://avatars3.githubusercontent.com/u/52195?s=400&v=4
# Links for template buttons
gitHubUrl: https://github.com/mcollina
linkedInUrl: https://www.linkedin.com/in/matteocollina
twitterUrl: https://twitter.com/matteocollina
# Order (lowest number first)
priority: 1
Testimonial stubs are used to power the quote, author and image used for testimonials as they appear on the homepage and and tool pages. Each testimonial uses the type
frontmatter key to relate it to the correct tool.
To update a testimonial, simply edit the frontmatter in their named markdown file. The options are as follows:
# Tool type
type: bubbleprof
# Quote
quote: Bubbleprof is kinda blowing my mind.
# Author of quote
author: Jerome Covington, Software Engineer Condé Nast
# Image of author
image: https://pbs.twimg.com/profile_images/766625364328218625/Pve_f1Qy_400x400.jpg
The options for the type
key are as follows:
doctor
bubbleprof
flame
heapprofiler
clinic
The clinic
option is used for the homepage
The Support Package stubs are used to power the contents of the comparison table on the support page. The frontmatter options are below. It is recommended that the promoted
option is applied to the middle package to honour the design and for visual clarity.
# Package title
title: Enterprise
# List of package features
features:
- Custom solutions to help you reach your goals
- Support bundles including other NearForm services
# Image to use in comparison
image: /assets/images/support-packages/enterprise.svg
# Button text to appear
buttonText: Contact us to learn more
# Accent colour
colour: '#825034'
# Ordering
priority: 1
FAQ stubs use frontmatter for the title to ensure they are all formatted consistently and priority for ordering, but make use of the the markdown body for the answer in order to provide content editors with enough flexibility to add links and other simple HTML to the answer if applicable.
# Heading
title: What does the Enterprise Tier provide?
# Ordering of FAQs as they appear in the Commercial Support page
priority: 3
During Gatsby startup, the /content/
directory is parsed and searched for any markdown files. A JSON tree representation of the directory is written into each nested project directory. The file name is <directory-name>-tree.json
.
This file is used to drive the navigation tree for the documentation part of the when retrieved via GraphQL for the documentation.js
template and passed to the SideNav
component by creating a JSON representation of the directory structure of every top level directory within the /content/
directory.
To re-generate this file, restart the server. These files are ignored in git
The generated tree JSON file also parses the file names for each markdown file and uses those as the default value for the tree item title. If the title contains -
or _
, they are turned into spaces ' '
. Each word is also capitalized.
To align the title of the markdown file the following rules apply when the tree is transformed from the JSON structure to the final navigation structure via GraphQL. Any frontmatter title
entries will be used as the displayed link value, otherwise the # Heading 1
from the markdown file is used as a fallback. If neither exist then the aforementioned default title value will be used as parsed from the markdown filename.
Given a markdown file with the following name getting-started.md
:
Priority title from frontmatter. Displayed in the SideNav
component as 'Getting started with Doctor'
title: Getting started with Doctor
Second priority if frontmatter title
does not exist. Displayed in the SideNav
component as 'Getting started with Clinic.js and Doctor'
# Getting started with Clinic.js and Doctor
Default from filename if neither frontmatter or h1
exist. Displayed in the SideNav
component as 'Getting Started'
Each Tree JSON file is loaded into Gatsby using gatsby-transformer-json at Gatsby startup. The field name follows the convention <projectFolder>Json
.
content/documentation/documentation-tree.json
can be queried in GraphQL with the field documentationJson
. Each get the value of this JSON, the template needs to query the links, titles, and entry for each project and pass the resulting links array into the NavigationTree
component.
fragment EntryFragment on File {
id
childMarkdownRemark {
htmlAst
fields {
slug
template
}
frontmatter {
title
priority
}
}
}
tableOfContents: documentationJson {
title
entry {
...EntryFragment
}
links {
title
entry {
...EntryFragment
}
links {
title
entry {
...EntryFragment
}
}
}
}
NOTE: The entire file is read statically with GraphQL meaning whenever a new nested directory is added to a project directory, the GraphQL query inside the template component MUST be updated to include the new nested structure. Otherwise, the new nested directory will NOT be visible.
A HubSpot form is integrated as part of the header CTA and homepage hero inside a modal. The config for this form can be found in the SiteConfig.js
file.
In order for the styling to take effect on the form, ensure the form is rendered rather than embedded by turning the 'Unstyled form' option on in HubSpot.
Talk to Sean Walsh for more information about HubSpot.
The fonts used on this website are:
Archia Regular (brand, licensed)
Archia Bold (brand, licensed)
Campton Bold (brand, licensed)
Space Mono (Google font, open license)
Fonts and the font-face CSS live inside the static/assets
directory. These are being used across brand assets from this website as a remote resource, so please DO NOT modify the contents, location or name of these files without first considering their usage in the following repos:
- node-clinic-data-server
- node-clinic-common
- node-clinic-flame
- node-clinic-bubbleprof
- node-clinic-doctor
- node-clinic-heap-profiler
Based off gatsby-start-docs and Gatsby Advanced Starter.