Getting started
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-sitecd example-siteyarn installgit 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.