DEV Community

Kematzy
Kematzy

Posted on

Storybook setup with Vite, Svelte Kit & Tailwind CSS

A working example of Storybook, with Vite, Svelte Kit and Tailwind CSS.

I was struggling with getting this to work, so I thought I would share how I managed to get things to work in the end.

The code can be found at github.com/kematzy/storybook-svelte-kit-vite-app.

 

 


1. Initial SvelteKit installation

Follow the initial instructions on the Svelte Kit page.

npm init svelte@next your-storybook-vite-sveltekit-app
Enter fullscreen mode Exit fullscreen mode

Choose the following setup options from those presented:

Question Choice
Which Svelte app template? Skeleton project
Use TypeScript? No
Add ESLint for code linting? Yes
Add Prettier for code formatting? Yes

Further Reading:

Change into your created directory and run npm install to install all packages:

cd your-storybook-vite-sveltekit-app

npm install
Enter fullscreen mode Exit fullscreen mode

Optionally, create a Git repository and commit all the changes.

git init

git add -A

git commit -m "Initial commit"
Enter fullscreen mode Exit fullscreen mode

Run some quick tests to ensure things are working.

npm run dev -- --open
Enter fullscreen mode Exit fullscreen mode

 

Svelte Kit Base

 


2. Add TailwindCSS support

Install Tailwind CSS support based upon their general instructions.

npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
Enter fullscreen mode Exit fullscreen mode

Add additional PostCSS packages for better CSS formatting.

npm install -D postcss-import postcss-nesting
Enter fullscreen mode Exit fullscreen mode
  • postcss-import supports multiple CSS files
  • postcss-nesting supports nested CSS format

Add support for parallel CSS generation.

npm install -D postcss-cli concurrently cross-env
Enter fullscreen mode Exit fullscreen mode

Create a postcss.config.cjs with the following contents:

module.exports = {
  plugins: {
    'postcss-import': {},
    'postcss-nesting': {},
    tailwindcss: {},
    autoprefixer: {},
  },
}
Enter fullscreen mode Exit fullscreen mode

Add the Tailwind config file:

npx tailwindcss init tailwind.config.cjs
Enter fullscreen mode Exit fullscreen mode

Then update tailwind.config.cjs with JIT and purge settings:

module.exports = {
  // ...
  mode: 'jit',
  purge: ['./src/**/*.svelte'],
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Create src/styles/tailwind.css with the following contents:

/* Injects Tailwind's base styles & any base styles registered by plugins. */
@tailwind base;

@layer base { /* custom CSS goes here */ }

/* Injects Tailwind's component classes & any component classes registered by plugins. */
@tailwind components;

@layer components { /* custom CSS goes here */ }

/* Injects Tailwind's utility classes & any utility classes registered by plugins. */
@tailwind utilities;

@layer utilities { /* custom CSS goes here */ }

/* Directive controlling where Tailwind injects responsive variations of utilities.
   By default Tailwind normally append these at the end of your stylesheet. */
@tailwind screens;
Enter fullscreen mode Exit fullscreen mode

Then update the script section in package.json as follows:

{
  "scripts": {
    "dev:only": "svelte-kit dev",

    "build:only": "svelte-kit build",

    "preview": "svelte-kit preview",

    "tailwind:watch": "cross-env TAILWIND_MODE=watch cross-env NODE_ENV=development  postcss src/styles/tailwind.css -o static/app.css -w",

    "tailwind:build": "cross-env TAILWIND_MODE=build cross-env NODE_ENV=production  postcss src/styles/tailwind.css -o static/app.css",

    "dev": "concurrently \"npm run dev:only\" \"npm run tailwind:watch\"",

    "build": "npm run tailwind:build && npm run build:only",

    // other defined scripts
  },
}
Enter fullscreen mode Exit fullscreen mode

Update the src/routes/index.svelte with Tailwind classes and import the src/styles/tailwind.css file for Vite hot reloading.

<script>
  import "../styles/tailwind.css";
</script>


<div class="flex flex-col justify-center align-middle p-4 mb-12">
  <h1 class="text-4xl text-center text-purple-700 font-light">Welcome to SvelteKit</h1>

  <p class="text-center mb-4 mt-2">
    Visit
    <a
      class="text-purple-400 hover:text-pink-700 hover:underline"
      href="https://kit.svelte.dev"
    >
      kit.svelte.dev
    </a>
    to read the documentation.
  </p>
</div>
Enter fullscreen mode Exit fullscreen mode



3. Add StyleLint support

Install stylelint related packages to silence any errors and/or warnings in your code editor.

npm install -D stylelint stylelint-config-standard stylelint-config-recommended
Enter fullscreen mode Exit fullscreen mode

Create a stylelintrc.json file with the following contents:

{
  "extends": [
    "stylelint-config-recommended"
  ],
  "processors": [],
  "rules": {
    "at-rule-no-unknown": [
      true,
      {
        "ignoreAtRules": [
          "tailwind",
          "apply",
          "variants",
          "responsive",
          "screen",
          "function",
          "each",
          "if",
          "else",
          "return",
          "layer"
        ]
      }
    ],
    "declaration-block-trailing-semicolon": null,
    "no-descending-specificity": [
      true,
      {
        "ignore": [
          "selectors-within-list"
        ]
      }
    ],
    "no-invalid-double-slash-comments": true,
    "block-no-empty": null
  }
}
Enter fullscreen mode Exit fullscreen mode

Optional: If you are using VS Code, then add a .vscode/settings.json file with the following settings:

{
  "css.validate": false,
  "less.validate": false,
  "scss.validate": false,
  "postcss.validate": false,
  "files.associations": {
    "*.css": "postcss"
  },
  "editor.formatOnSave": false,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.html": true
  },
  "stylelint.enable": true,
  "stylelint.validate": [
    "css",
    "postcss"
  ],
  "typescript.disableAutomaticTypeAcquisition": true,
  "javascript.format.enable": false
}
Enter fullscreen mode Exit fullscreen mode

Run some quick tests to ensure the Tailwind implementation is working.

npm run dev -- --open
Enter fullscreen mode Exit fullscreen mode

 

Svelte Kit with Tailwind

 


If you created a Git repository already, then this is a great time to commit all the changes.

git add -A  && git commit -m "Added Tailwind, PostCSS & Stylelint support"
Enter fullscreen mode Exit fullscreen mode

4. Install and Setup Storybook

So far things have been fairly straightforward and hopefully without any errors.

Follow the instructions in the Storybook's Svelte Getting Started and run:

npx sb init
Enter fullscreen mode Exit fullscreen mode

And you will see output similar to this:

npx sb init

 sb init - the simplest way to add a Storybook to your project.

✓ Detecting project type.
info Configuring preprocessor from 'svelte.config.js'

added 1357 packages, and audited 2102 packages in 33s

✓ Preparing to install dependencies.
  up to date, audited 2102 packages in 2s

✓ To run your Storybook, type:

   npm run storybook

For more information visit: https://storybook.js.org
Enter fullscreen mode Exit fullscreen mode

Try to start Storybook in development mode:

npm run storybook
Enter fullscreen mode Exit fullscreen mode

At this point you will very likely hit a number of errors along these lines:

npm run storybook

> ~TODO~@0.0.1 storybook
> start-storybook -p 6006

info @storybook/svelte v6.3.6
info
ERR! Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: [$HOME]/DEV/your-storybook-vite-sveltekit-app/.storybook/main.js
ERR! require() of ES modules is not supported.
ERR! require() of [$HOME]/DEV/your-storybook-vite-sveltekit-app/.storybook/main.js from [$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
ERR! Instead rename main.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from [$HOME]/DEV/your-storybook-vite-sveltekit-app/package.json.
ERR!
ERR!     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1080:13)
ERR!     at Module.load (internal/modules/cjs/loader.js:928:32)
ERR!     at Function.Module._load (internal/modules/cjs/loader.js:769:14)
ERR!     at Module.require (internal/modules/cjs/loader.js:952:19)
ERR!     at require (internal/modules/cjs/helpers.js:88:18)
ERR!     at interopRequireDefault ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:64:16)
ERR!     at serverRequire ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:101:10)
ERR!     at getPreviewBuilder ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-server/dist/cjs/utils/get-preview-builder.js:25:55)
ERR!     at buildDevStandalone ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-server/dist/cjs/build-dev.js:99:71)
ERR!     at async buildDev ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-server/dist/cjs/build-dev.js:154:5)
ERR!  Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: [$HOME]/DEV/your-storybook-vite-sveltekit-app/.storybook/main.js
ERR! require() of ES modules is not supported.
ERR! require() of [$HOME]/DEV/your-storybook-vite-sveltekit-app/.storybook/main.js from [$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
ERR! Instead rename main.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from [$HOME]/DEV/your-storybook-vite-sveltekit-app/package.json.
ERR!
ERR!     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1080:13)
ERR!     at Module.load (internal/modules/cjs/loader.js:928:32)
ERR!     at Function.Module._load (internal/modules/cjs/loader.js:769:14)
ERR!     at Module.require (internal/modules/cjs/loader.js:952:19)
ERR!     at require (internal/modules/cjs/helpers.js:88:18)
ERR!     at interopRequireDefault ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:64:16)
ERR!     at serverRequire ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:101:10)
ERR!     at getPreviewBuilder ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-server/dist/cjs/utils/get-preview-builder.js:25:55)
ERR!     at buildDevStandalone ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-server/dist/cjs/build-dev.js:99:71)
ERR!     at async buildDev ([$HOME]/DEV/your-storybook-vite-sveltekit-app/node_modules/@storybook/core-server/dist/cjs/build-dev.js:154:5) {
ERR!   code: 'ERR_REQUIRE_ESM'
ERR! }

WARN Broken build, fix the error above.
WARN You may need to refresh the browser.

Enter fullscreen mode Exit fullscreen mode

If you created a Git repository already, then this is another great time to commit all the changes added before we change them.

git add -A
git commit -m "Added Storybook support (default with errors)"
Enter fullscreen mode Exit fullscreen mode

To fix these errors we need to update the installed @storybook packages to version ^6.4.0-alpha.22 or later.

I recommend removing the existing node_modules folder and package-lock.json from your project folder.

rm -rf node_modules

rm package-lock.json
Enter fullscreen mode Exit fullscreen mode

And then update the following packages in the package.json file to the latest version.

{
  // snip
  "devDependencies": {
    "@storybook/addon-actions": "^6.4.0-alpha.22",
    "@storybook/addon-essentials": "^6.4.0-alpha.22",
    "@storybook/addon-links": "^6.4.0-alpha.22",
    // snip
  },
  // snip
}
Enter fullscreen mode Exit fullscreen mode

NOTE!

If you try to update the "@storybook/svelte package to ^6.4.0-alpha.22 you will run into installation errors
so we leave it at the default for now.

Re-install all the npm packages again.

npm install
Enter fullscreen mode Exit fullscreen mode

The we need to install @storybook/addon-docs package that is missing:

npm install -D @storybook/addon-docs@6.4.0-alpha.22
Enter fullscreen mode Exit fullscreen mode

While we are installing packages, we also need to install the storybook-builder-vite package to make the Vite actually stuff work:

npm install -D storybook-builder-vite
Enter fullscreen mode Exit fullscreen mode

Then we need to rename svelte.config.js to svelte.config.cjs...

mv svelte.config.js svelte.config.cjs
Enter fullscreen mode Exit fullscreen mode

and convert the format as follows:

/** @type {import('@sveltejs/kit').Config} */
module.exports = {
  config: {
    kit: {
      // hydrate the <div id="svelte"> element in src/app.html
      target: '#svelte',
    },
  },
}
Enter fullscreen mode Exit fullscreen mode

As well as rename .storybook/main.js to .storybook/main.cjs...

mv .storybook/main.js .storybook/main.cjs
Enter fullscreen mode Exit fullscreen mode

and convert the format as follows:

module.exports = {
  core: {
    builder: "storybook-builder-vite"
  },
  stories: [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx|svelte)"
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-svelte-csf"
  ],
  svelteOptions: {
    preprocess: require("../svelte.config.cjs").preprocess
  }
}
Enter fullscreen mode Exit fullscreen mode

NOTE!

The added support for Vite through the following added code snippet:

core: {
  builder: "storybook-builder-vite"
}
Enter fullscreen mode Exit fullscreen mode

And then, finally, we need to just rename .storybook/preview.js to .storybook/preview.cjs and not change the contents:

mv .storybook/preview.js .storybook/preview.cjs
Enter fullscreen mode Exit fullscreen mode

If you created a Git repository already, then this is another great point in time to commit all the changes.

git add -A  && git commit -m "Fixed Storybook errors"
Enter fullscreen mode Exit fullscreen mode




5. Start Storybook again

If you have followed the above instructions everything should hopefully work when you start Storybook again:

npm run storybook
Enter fullscreen mode Exit fullscreen mode

 

Storybook, Svelte Kit, Vite & Tailwind

 

Found something wrong?

Open a PR if anything is wrong or things can be done in a better and faster way.


SOURCES OF INFORMATION

Top comments (6)

Collapse
 
koder profile image
Ben Woodward • Edited

It seems this is now unnecessary, and all you need to do is the following:

  • Add .storybook/pakckage.json containing:
{
    "type": "commonjs"
}
Enter fullscreen mode Exit fullscreen mode
  • change line 12 of .storybook/main.js from

"preprocess": require("../svelte.config.js").preprocess

to:

"preprocess": import("../svelte.config.js").preprocess

source: github.com/storybookjs/storybook/i...

Collapse
 
chranditho profile image
Christoph • Edited

this worked for me. thanks for the comment!
you do have a typo in ./storybook/package.json

Collapse
 
beebase profile image
Maarten Berkenbosch • Edited

Thanks a lot for sharing this info!
Does anyone know how to configure the storybook main.cjs file in order to make an alias work?
This is how I've set up an alias in vitejs

vite.config.cjs

export default defineConfig({
  plugins: [svelte()],
  server: {
    fs: {
      allow: ['..']
    }
  },
  resolve: {
    alias: [
      {
        find: '@',
        replacement: '/.../my-app/src',
      }
    ]
  },
  ...
})
Enter fullscreen mode Exit fullscreen mode
Collapse
 
beebase profile image
Maarten Berkenbosch

ah, found it:

module.exports = {
  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx|svelte)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-svelte-csf"
  ],
  "core": {
    "builder": "storybook-builder-vite"
  },
  "svelteOptions": {
    "preprocess": require("../svelte.config.cjs").preprocess
  },
  async viteFinal(config) {
    config.resolve.alias = {
      "@": "/.../my-app/src",
    };

    return config;
  }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
camiloforero profile image
camiloforero

This is cool, by the edge of frontend creation technology

Collapse
 
danielrios549 profile image
Daniel Rios

How to get the default values from component?