Getting started

Welcome to Spark Web — Brighte’s Design System. In this guide we are going to go through the steps necessary to get started with the React component library from our Design System.

What is React?

Our component library is built with React, a popular JavaScript library for building User Interfaces.

If you’re new to React we recommend going through the official Quick Start guide.

Creating a new project with Spark Web

Using our starter project

If you'd just like to get up and running quicking with a Next.js app that is already set up to work with Spark Web, you can use our starter project:

Clone down a copy with degit:

npx degit brighte-labs/spark-web/examples/example-site example-site
cd example-site
yarn install
git init . && git add . && git commit -m "Init"

Now if you run yarn dev you should be able to view a preview of the Next.js app running on port 3001.

Starting from scratch

If you want to add Spark Web to an existing application, or you just want to start from scratch you can follow the below steps instead.

This guide assumes you're using Next.js. Spark Web will work in other React frameworks but the steps will vary slightly.

1. Create a fresh Next.js app

yarn create next-app --typescript

Note: We're using the typescript flag here but Spark Web will work in a regular JavaScript application if that's what you prefer.

2. Strip out the stuff we don't need

The Next.js starter comes with some boilerplate that we probably don't want. Let's get rid of it!

Delete the api folder in the pages directory.

Delete the styles folder from the root of your application.

Delete the first line in _app that imports global styles (import '../styles/globals.css').

Delete the custom styles in pages/index. Here is a stripped down version you can copy/paste:

import type { NextPage } from 'next';
import Head from 'next/head';
import Image from 'next/image';
const Home: NextPage = () => {
return (
<div>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</h1>
</main>
</div>
);
};
export default Home;

3. Install required Spark Web packages

yarn add @spark-web/box @spark-web/columns @spark-web/container @spark-web/core @spark-web/heading @spark-web/inline @spark-web/link @spark-web/next-utils @spark-web/row @spark-web/stack @spark-web/text @spark-web/theme

This will install a handful of the most important packages that you will need to get started. Spark Web is bundled up into small packages so you can choose what components you do and don't need.

4. Set up the SparkProvider

In a Next.js app, the root of your application is the _app file. This is a good place to put global providers that need to be available on every route.

Import the SparkProvider from @spark-web/core and wrap <Component /> with it.

This provides the following functionality to Spark Web:

  • A theme provider
  • A link component provider
  • An id provider (prior to React 18 this is used to generate unique ids which we used to label elements for assistive technology amongst other things)
  • A minimal CSS reset
  • Calls useFocusVisible which we use to show focus rings when navigating with keyboard, but not when using a pointing device (such as a mouse or trackpad).

SparkProvider takes two optional props: linkComponent and theme. You can use these to override some default functionality. In this example we want to provide a custom link component.

Next.js comes with a Link component for doing client-side page transitions that don't require the full page refresh you'd get with a regular <a> element.

If we pass a special link component to the SparkProvider, it will be used by all of the link components from Spark Web (which at the time of writing this guide are; Link, ButtonLink, NavLink and TextLink).

The @spark-web/link package comes with a makeLinkComponent function that we can use to create a link component that the SparkProvider knows how to use. For Next.js applications, we've made it even easier for you and provided a UniversalNextLink component as part of the @spark-web/next-utils package. This component uses the Next.js link component for client-side transitions and will fall back to using an <a> for external links.

Now your _app file should look something like this:

import { SparkProvider } from '@spark-web/core';
import { UniversalNextLink } from '@spark-web/next-utils';
import type { AppProps } from 'next/app';
function MyApp({ Component, pageProps }: AppProps) {
return (
<SparkProvider linkComponent={UniversalNextLink}>
<Component {...pageProps} />
</SparkProvider>
);
}
export default MyApp;

5. Update the index page to use Spark Web components

Now you can use Spark Web components to build whatever page you like. Here is a basic starting point if you just want to copy/paste something:

import { Container } from '@spark-web/container';
import { Heading } from '@spark-web/heading';
import { Stack } from '@spark-web/stack';
import { Text } from '@spark-web/text';
import type { NextPage } from 'next';
import Head from 'next/head';
const Home: NextPage = () => {
return (
<Container size="xlarge">
<Head>
<title>Spark Web App</title>
<meta name="description" content="Spark Web" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Stack as="main" paddingY="xxlarge" gap="xxlarge" flex={1}>
<Heading level="1" align="center">
Spark Web
</Heading>
<Text size="large" align="center">
Get started by editing <code>pages/index.tsx</code>
</Text>
</Stack>
</Container>
);
};
export default Home;

6. Set up Server Side Rendering

If you were to deploy the app as is, you might notice if you're on a slow connection, that your styles don't load immediately.

Spark Web uses Emotion CSS for styling — a CSS-in-JS library.

Since Emotion generates our styles using JavaScript our HTML is often ready before that JavaScript has finished loading and so we might see a flash of unstyled content. This is where server-side rendering comes in.

Spark Web has a propsWithCssText function which takes the initial page props on the server (before the HTML makes it's way to the client) and works out what styles it needs to generate. It then inlines the CSS into a <style> tag in the head of the document so that all the CSS needed to view the page is loaded alongside the HTML.

To use it, we need to set up a custom document.

Inside the pages directory, create a new file called _document.tsx and paste in the following code:

import { propsWithCssText } from '@spark-web/next-utils';
import Document, { DocumentContext, DocumentInitialProps } from 'next/document';
class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
): Promise<DocumentInitialProps> {
const initialProps = await Document.getInitialProps(ctx);
return propsWithCssText(initialProps);
}
}
export default MyDocument;

This is straight from the TypeScript example in the Next.js docs. The only thing we've changed is instead of return initialProps, we pass it to propsWithCssText and return that instead.

Now if use your browsers dev tools to view source and inspect the <head> of the page, you should see something like this:

<style data-emotion="css yppvau 1f1owa 1wldsp1 gw2nzi" data-s="">.css-yppvau{margin:0;padding:0;border:0;box-sizing:border-box;font-size:100%;font:inherit;vertical-align:baseline;-webkit-tap-highlight-color:transparent;width:100%;margin-left:auto;margin-right:auto;max-width:1400px;}.css-1f1owa{margin:0;padding:0;border:0;box-sizing:border-box;font-size:100%;font:inherit;vertical-align:baseline;-webkit-tap-highlight-color:transparent;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-bottom:32px;padding-top:32px;-webkit-align-items:stretch;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;gap:32px;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex:1;-ms-flex:1;flex:1;}.css-1wldsp1{margin:0;padding:0;border:0;box-sizing:border-box;font-size:100%;font:inherit;vertical-align:baseline;-webkit-tap-highlight-color:transparent;color:#1a2a3a;font-family:"Aestetico",ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-weight:600;text-align:center;font-size:2.1875rem;line-height:2.25rem;}.css-1wldsp1::before{content:" ";display:table;margin-bottom:-0.1683em;}.css-1wldsp1::after{content:" ";display:table;margin-top:-0.1943em;}@media screen and (min-width: 740px){.css-1wldsp1{font-size:2.1875rem;line-height:2.75rem;}.css-1wldsp1::before{content:" ";display:table;margin-bottom:-0.2826em;}.css-1wldsp1::after{content:" ";display:table;margin-top:-0.3086em;}}.css-gw2nzi{margin:0;padding:0;border:0;box-sizing:border-box;font-size:100%;font:inherit;vertical-align:baseline;-webkit-tap-highlight-color:transparent;color:#1a2a3a;font-family:"Aestetico",ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-weight:400;font-size:1.1875rem;line-height:1.75rem;display:block;text-align:center;}.css-gw2nzi::before{content:" ";display:table;margin-bottom:-0.3908em;}.css-gw2nzi::after{content:" ";display:table;margin-top:-0.4168em;}@media screen and (min-width: 740px){.css-gw2nzi{font-size:1.1875rem;line-height:1.75rem;}.css-gw2nzi::before{content:" ";display:table;margin-bottom:-0.3908em;}.css-gw2nzi::after{content:" ";display:table;margin-top:-0.4168em;}}</style>

Those are the inlined styles now getting sent as part of the pages HTML. No more flash of unstyled content!

That's it

Now you can start using Spark Web to build your applications UI!

If you need help, feel free to reach out in the #spark-web-support Slack channel.

© 2023 Brighte Capital Pty Ltd