diff --git a/MIGRATION.md b/MIGRATION.md
index 6e48d1e75a4d..7db3b2fab2ff 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -19,6 +19,7 @@
- [Removed renderCurrentStory event](#removed-rendercurrentstory-event)
- [Removed hierarchy separators](#removed-hierarchy-separators)
- [Client API changes](#client-api-changes)
+ - [Removed support for duplicate kinds](#removed-support-for-duplicate-kinds)
- [Removed Legacy Story APIs](#removed-legacy-story-apis)
- [Can no longer add decorators/parameters after stories](#can-no-longer-add-decoratorsparameters-after-stories)
- [Changed Parameter Handling](#changed-parameter-handling)
@@ -414,6 +415,29 @@ addons.setConfig({
### Client API changes
+#### Removed support for duplicate kinds
+
+In 6.0 we removed the ability to split a kind's (component's) stories into multiple files because it was causing issues in hot module reloading (HMR).
+
+If you had N stories that contained `export default { title: 'foo/bar' }` (or the MDX equivalent ``), Storybook will now throw the error `Duplicate title '${kindName}' used in multiple files`.
+
+To split a component's stories into multiple files, e.g. for the `foo/bar` example above:
+
+- Create a single file with the `export default { title: 'foo/bar' }` export, which is the primary file
+- Comment out or delete the default export from the other files
+- Re-export the stories from the other files in the primary file
+
+So the primary example might look like:
+
+```js
+export default { title: 'foo/bar' };
+export * from './Bar1.stories'
+export * from './Bar2.stories'
+export * from './Bar3.stories'
+
+export const SomeStory = () => ...;
+```
+
#### Removed Legacy Story APIs
In 6.0 we removed a set of APIs from the underlying `StoryStore` (which wasn't publicly accessible):
diff --git a/addons/docs/docs/recipes.md b/addons/docs/docs/recipes.md
index 5ee6a4ee1c5d..21525c081e7a 100644
--- a/addons/docs/docs/recipes.md
+++ b/addons/docs/docs/recipes.md
@@ -44,11 +44,12 @@ Perhaps you want to write your stories in CSF, but document them in MDX? Here's
import React from 'react';
import { Button } from './Button';
-export default {
- title: 'Demo/Button',
- component: Button,
- includeStories: [], // or don't load this file at all
-};
+// NOTE: no default export since `Button.stories.mdx` is the story file for `Button` now
+//
+// export default {
+// title: 'Demo/Button',
+// component: Button,
+// };
export const basic = () => ;
basic.parameters = {
@@ -60,7 +61,7 @@ basic.parameters = {
```md
import { Meta, Story } from '@storybook/addon-docs/blocks';
-import \* as stories from './Button.stories.js';
+import * as stories from './Button.stories.js';
import { SomeComponent } from 'path/to/SomeComponent';
diff --git a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js
index 5ecfbc6b342c..a5dab9fb2b7d 100644
--- a/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js
+++ b/examples/official-storybook/stories/addon-docs/csf-with-mdx-docs.stories.js
@@ -1,10 +1,12 @@
import React from 'react';
import { Button } from '@storybook/react/demo';
-export default {
- title: 'Addons/Docs/csf-with-mdx-docs',
- component: Button,
- includeStories: [], // or don't load this file at all
-};
+// NOTE: commented out default since these stories are re-exported
+// in the primary file './csf-docs-with-mdx-docs.stories.mdx'
+//
+// export default {
+// title: 'Addons/Docs/csf-with-mdx-docs',
+// component: Button,
+// };
export const basic = () => ;
diff --git a/lib/core/src/client/preview/loadCsf.ts b/lib/core/src/client/preview/loadCsf.ts
index ee982cdb907f..7c308d7aab4f 100644
--- a/lib/core/src/client/preview/loadCsf.ts
+++ b/lib/core/src/client/preview/loadCsf.ts
@@ -22,6 +22,9 @@ const loadStories = (
framework: string,
{ clientApi, storyStore }: { clientApi: ClientApi; storyStore: StoryStore }
) => () => {
+ // Make sure we don't try to define a kind more than once within the same load
+ const loadedKinds = new Set();
+
let reqs = null;
// todo discuss / improve type check
if (Array.isArray(loadable)) {
@@ -106,6 +109,18 @@ const loadStories = (
args: kindArgs,
argTypes: kindArgTypes,
} = meta;
+
+ if (loadedKinds.has(kindName)) {
+ throw new Error(
+ dedent`
+ Duplicate title '${kindName}' used in multiple files; use unique titles or a primary file for '${kindName}' with re-exported stories.
+
+ https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#removed-support-for-duplicate-kinds
+ `
+ );
+ }
+ loadedKinds.add(kindName);
+
// We pass true here to avoid the warning about HMR. It's cool clientApi, we got this
// todo discuss: TS now wants a NodeModule; should we fix this differently?
const kind = clientApi.storiesOf(kindName, true as any);