# Developing
> Vera has everything you need to get started building web interfaces at Gemini Suite. Develop a consistent and accessible user interfaces much faster using a range of pre-built components.

## Developing

## Authenticating to package registry

Since `@volue` is a private NPM scope, your project (both locally and in CI pipeline) needs to be authenticated with NPM registry to fetch packages.

Vera packages are published to both official [npmjs.com registry](https://www.npmjs.com/) and our organization's [Github Package Registry](https://github.com/orgs/Volue/packages).

<Tabs.Root
  defaultValue="npm"
>
  <Tabs.List css={{ marginBottom: '$spacingM' }}>
    <Tabs.Trigger value="npm">{'NPM'}</Tabs.Trigger>
    <Tabs.Trigger value="ghPackages">{'GitHub packages'}</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Content value="npm">

The best way to authenticate with [npmjs.com registry](https://www.npmjs.com/) is using an [access token](https://docs.npmjs.com/about-access-tokens).
You can find pre-generated authentication token with read-only permissions required to download Vera packages in the [wiki page on GitHub](https://github.com/Volue/vera/wiki/NPM-authentication-token).

```bash
# 1. Do this on your local machine and commit the `.npmrc` to git
cd path/to/your/app
echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' >> .npmrc

# 2. Add this environment variable locally
# Substitute `READ_ONLY_NPM_TOKEN` with a real token:
# https://github.com/Volue/vera/wiki/NPM-authentication-token
export NPM_TOKEN=READ_ONLY_NPM_TOKEN

# 3. When using Github Actions for CI/CD pipeline, point `NPM_TOKEN` environment
# variable to org-wide `secrets.GEMINI_SUITE_NPM_TOKEN`, otherwise define a new
# secret using the token from previous step.

```

<Callout variant="tip">

If, for some reason, you're not able to access the [NPM authentication token page](https://github.com/Volue/vera/wiki/NPM-authentication-token), please contact the [Design System team](https://github.com/orgs/Volue/teams/design-system).

</Callout>

<Card
  href="https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow"
  title="NPM guide on using private packages in a CI/CD workflow"
  actionIcon="externalLink"
/>

  </Tabs.Content>
  <Tabs.Content value="ghPackages">

By default, the `npm` CLI utility is configured to download packages from [official NPM registry](https://www.npmjs.com/).
To fetch Vera from [Github Packages](https://docs.github.com/packages), you need to change registry url and specify a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with read-only permissions inside _.npmrc_ file.

```bash
# 1. Do this on your local machine and commit the `.npmrc` to git
cd path/to/your/app
cat > .npmrc << EOF
registry=https://npm.pkg.github.com/volue
//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGES_PAT}
EOF

# 2. Add this environment variable both locally and on your CI/CD
# Substitute `READ_ONLY_GITHUB_PAT` with a real token:
export GITHUB_PACKAGES_PAT=READ_ONLY_GITHUB_PAT
```

<Callout variant="important">

`READ_ONLY_GITHUB_PAT` should be a [classic personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#personal-access-tokens-classic) with `read:packages` scope.

</Callout>

<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '2'
  }}
  columnGap="spacingL"
>
  <GridItem>
    <Card
      href="https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry"
      title="Guide on using GitHub Packages registry"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.blog/2019-09-11-proxying-packages-with-github-package-registry-and-other-updates/"
      title="Proxying packages from npmjs.com"
      actionIcon="externalLink"
    />
  </GridItem>
</Grid>

  </Tabs.Content>
</Tabs.Root>

---

## Installation

Inside your project directory, install Vera by running either of the following:

```bash
npm install @gemini-suite/vera @gemini-suite/vera-react --save
```

```bash
yarn add @gemini-suite/vera @gemini-suite/vera-react
```

<Callout variant="tip">

Bleeding edge pre-release version with the most recent features, can be installed by appending `@next` tag to the package names:

```bash
yarn add @gemini-suite/vera@next @gemini-suite/vera-react@next
```

</Callout>

---

## Include Vera core assets

<Callout variant="tip">

The guide below is useful for custom setups. As long as you're using [one of our starter project templates](#example-react-projects), you can skip these instructions, as these templates are already preconfigured.

</Callout>

For Vera to work correctly, you need to include its core assets, such as stylesheets, icons and web fonts.

To copy core assets from `node_modules/@gemini-suite/vera` to a location where you store your other bundled and minified assets for production, you may use `copy-vera-assets` command:

```bash
npx copy-vera-assets ./dist
# or
yarn copy-vera-assets ./dist
```

<Callout variant="tip">

`copy-vera-assets` will create a directory named `vera` in the location you’ve specified (`./dist` in the example above). See `copy-vera-assets -h` for more information.

</Callout>

It is recommended to add a script to your `package.json` that runs `copy-vera-assets` and call it whenever the build is executed to make sure you’ve always got the latest assets copied over:

```js
  "scripts": {
    "sync-vera-assets": "npx copy-vera-assets ./public",
    "build": "npm run sync-vera-assets && react-scripts build",
    "start": "npm run sync-vera-assets && react-scripts start"
  }
}
```

Alternatively, you could use tools such as [CopyWebpackPlugin](https://webpack.js.org/plugins/copy-webpack-plugin/) to move core Vera resources to your assets directory as part of your build process.

### Include assets in your HTML template

Once you have a copy task in place and and the assets are copied over, you can serve them using `<link>` tags in your root HTML template.

- Add links to favicons

- Add inline style with @font-face rules in the `<head>` to load initial, highly optimized versions of our web fonts.

  <Callout variant="tip">

  Remember to preload the initial web fonts using `<link rel=”preload”>`.

  </Callout>

- Inline `vera-head.min.js` in the `<head>` of your HTML template. This is a small chunk of logic that will asynchronously load full versions of our web fonts to enable more stylistic variants and features.

  <Callout variant="tip">

  `vera-head.min.js` could be specified as `<script src="vera/vera-head.min.js">`,
  however it's best to save additional network request for a
  render-blocking resource.

  You can achieve the inlining by using interpolation syntax of [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin#writing-your-own-templates) (see final markup example below).

  </Callout>

  <Callout variant="tip">

  You can customize the path to the web fonts directory by adding `<meta name="fontsDir" content="/path/to/fonts">` in the `<head>`. By default fonts will be looked up in `/fonts` directory.

  </Callout>

- Add link to the CSS bundle to include the core Vera styles.

- Inline [the SVG sprite with Vera icons](/tokens/icons#usage)

The final markup should resemble:

<Accordion>
  <AccordionItem title={<InlineCode>{'index.html'}</InlineCode>}>

```html showLineNumbers=true
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta name="theme-color" content="#00829b" />
    <title>...</title>

    <!-- Favicons -->
    <!-- make sure to place `favicon.ico` in the root of your web app (required for legacy browsers) -->
    <link rel="icon" href="/favicon.ico" sizes="any" />
    <link rel="icon" type="image/svg+xml" href="/vera/images/favicon.svg" />
    <link
      rel="icon"
      type="image/png"
      sizes="192x192"
      href="/vera/images/favicon-192.png"
    />
    <link rel="apple-touch-icon" href="/vera/images/favicon-180.png" />

    <!-- Vera webfonts -->
    <link
      rel="preload"
      href="/vera/fonts/SourceSansPro-Regular-initial.woff2"
      as="font"
      type="font/woff2"
      crossorigin
    />
    <link
      rel="preload"
      href="/vera/fonts/Swizzy-Regular.woff2"
      as="font"
      type="font/woff2"
      crossorigin
    />
    <style>
      @font-face {
        font-family: 'Source Sans Pro';
        src:
          url(/vera/fonts/SourceSansPro-Regular-initial.woff2) format('woff2'),
          url(/vera/fonts/SourceSansPro-Regular-initial.woff) format('woff');
        font-display: swap;
      }
      @font-face {
        font-family: 'Swizzy';
        src:
          url(/vera/fonts/Swizzy-Regular.woff2) format('woff2'),
          url(/vera/fonts/Swizzy-Regular.woff) format('woff');
        font-display: swap;
      }
    </style>
    <!-- vera-head.min.js inlined -->
    <script>
      <%= require('!!raw-loader!@gemini-suite/vera/dist/core/vera-head.min').default %>
    </script>

    <!-- Vera core styles -->
    <link rel="stylesheet" href="vera/vera.min.css" />
  </head>
  <body>
    <!-- Embedded Vera icons sprite -->
    <div id="svgSpritePlaceholder" class="is-hidden" aria-hidden="true">
      <%=
      require('!!raw-loader!@gemini-suite/vera/dist/core/sprite.svg').default %>
    </div>

    <div id="appRoot"></div>
  </body>
</html>
```

  </AccordionItem>
</Accordion>

## Use the components

All components are available as named exports from `@gemini-suite/vera-react`.
Import any of the components in your React project and use them in your interface:

```jsx
import { Collapsible, Button, SvgIcon } from '@gemini-suite/vera-react';

const Component = () => {
  return (
    <Collapsible.Root>
      <Collapsible.Trigger as={Button} variant="outline">
        <SvgIcon iconName="chevronDown" /> {'Toggle panel'}
      </Collapsible.Trigger>
      <Collapsible.Panel>{'Panel content'}</Collapsible.Panel>
    </Collapsible.Root>
  );
};
```

Refer to the individual component documentation for recommended usage and API references for each component.

## Styling APIs

### css

The `css` property is available on all of our components to allow you to contextually style them when necessary.
It provides a superset of CSS (i.e. it contains all CSS properties and selectors in addition to custom ones) so it's intuitive to pick up and start working with right away if you're comfortable with CSS.
You can pass in an object of CSS key-value pairs and the component will apply those styles as a class on the rendered component.

The benefit of using the `css` prop as opposed to writing inline styles is that we can directly access values from our design tokens to ensure consistency, write responsive styles by referring to the breakpoints defined in the theme etc:

```jsx
import { Box } from '@gemini-suite/vera-react';

<Box
  css={{
    // we can write standard CSS here
    color: 'red',

    // we can also access design tokens
    backgroundColor: '$backgroundNeutralSubtle',
    padding: '$spacingM',

    // write inline responsive styles
    '@mqLargeAndUp': {
      color: '$foregroundAccentModerate'
    },

    // and utilise shorthand utilities
    mb: '$spacingXl'
  }}
/>;
```

<Callout variant="tip">

[Box component](/components/layout/box) is a low-level primitive that lets you work with the `css` prop.

</Callout>

<Callout variant="tip">

When working in a TypeScript codebase our design token options will show up with autocompletion depending on the CSS property used.

</Callout>

The `css` prop is great for customizing only a specific instance of a given component, by defining one-off styles.

### styled

`@gemini-suite/vera-react` also exports the underlying `styled()` function that is used to create styled components with access to the `css` prop.

```jsx
import { styled } from '@gemini-suite/vera-react';

const MyStyledComponent = styled('div', {
  color: '$foregroundAccent',

  size: {
    small: {
      padding: '$spacingS'
    },
    large: {
      padding: '$spacingL'
    }
  }
});

() => <MyStyledComponent size="large" />;
```

<Callout variant="tip">

[Box component](/components/layout/box) is just a `styled` div element.

</Callout>

In contrast to the `css` prop, `styled()` function is ideal for building components that need to support a wide variety of contexts.
It allows you to create custom components, with similar capabilities as Vera's standard components.

In addition to the base component styles, `styled()` lets you define a single variant, multiple variants, and even compound variants which allow you to define styles based on a combination of variants.
Those variants can be applied conditionally or responsively.

Refer to the [Stitches docs](https://stitches.dev/docs/styling) to read more about the difference between `css` and `styled()`.

## Example React projects

Below you will find various project templates on GitHub, demonstrating the integration of Vera with popular bundlers/frameworks and very basic components usage.

<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '2'
  }}
  columnGap="spacingL"
>
  <GridItem>
    <Card
      href="https://github.com/Volue/vera-vite-example"
      title="Vite example"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.com/Volue/vera-nextjs-app-router-example"
      title="Next.js with app router example"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.com/Volue/vera-nextjs-example"
      title="Next.js with pages router example (deprecated)"
      actionIcon="externalLink"
    />
  </GridItem>
</Grid>
