What is actually in the generated files. The model behind it is How export works; this is the lookup for someone reading the output.
Each component exports as two files, named after the component in lower case:
<name>.tsx — the component, its types and its defaults.
<name>.module.scss — its styles, as a CSS module.
Both open with:
// This file is generated by Misaki Studio. Do not edit.Take that literally — re-exporting overwrites them. To add behavior, import the generated component into a file of your own and wrap it.
Components also carry "use client".
export const Component = ({
className = "",
style,
divProps,
properties = DefaultProps,
variant,
onStatesChange,
children,
}) => { ... }Every parameter is optional.
className — your own classes, merged with the generated ones.
style — inline overrides from outside.
divProps — props forwarded to the root element, including a ref.
properties — the component's own props — the ones the design declares. Defaults to DefaultProps.
variant — an array of variant keys, key-checked.
onStatesChange — called when the component's internal state changes.
children — content for the named slots the design declares.
Design properties arrive under properties, not spread onto the component — properties.title, not title.
A component exports the types its design declares — a facet the design never uses is left out, so a component with no variants exports no Variants:
export type Props = { title: string };
export type States = { open: boolean };
export const Variants = { default: undefined, sizeSmall: "Enn689k", ... };
export type Children = { left?: React.ReactNode; right?: React.ReactNode };
export const DefaultProps: Props = { title: "Title" };Variants maps each declared variant to its generated class — default maps to undefined, since it is the base style — and the prop that consumes it is:
variant?: (keyof typeof Variants)[];An array, so variants compose, and key-checked, so a typo is a compile error.
A page exports a Next.js page rather than a named component:
export default function Page() { ... }
Page.getLayout = function getLayout(page: ReactNode) { ... }That is the main difference: components are imported and placed; pages are routes.
Class names look like .E6a4ujj. They are generated per element, referenced through the CSS module as styles["E6a4ujj"], and stable across exports — the same element keeps its class, so diffs stay readable.
They are meaningless by design. The CSS module scopes them, so they cannot collide with your own styles, and nothing in your app should target them directly.
Alongside them each instance gets a runtime id from msi.utils.getCount(), which is what keeps one instance's state-driven styles from affecting another's.
Hover, focus and active are plain CSS, not JavaScript:
.Eag51ew:hover { ... }
.Eag51ew:focus { ... }No event handlers, no state, no re-render.
A component with a timeline exports its animation as data and lets the runtime play it:
export const timelineData = (id: string): msi.timeline.Timelines => ({ ... });The component consumes it as:
const { timelines } = msi.timeline.useTimeline(
timelineData(id),
{ OnScroll: msi.timeline.TimelineCommandOption.INIT },
styles,
rootElement.current,
);The second argument is how the timeline is triggered — on scroll, on appear, or from your own logic.
import * as msi from "misaki-studio-internal";msi is what a design cannot express as plain markup: the timeline player, the loop helpers, text coercion (msi.utils.toText), the per-instance id counter, and the DivProps type. It is a real dependency — the generated code does not inline it.
design-system/Tokens export as a folder of typed helpers beside the CSS variables they name:
colors.ts · fonts.ts · spacing.ts · radius.ts — token name maps.
images.tsx — SVG tokens, as React components.
audios.ts — the Audios token map plus the sound-playback runtime.
themes.tsx — the ThemesLayer provider and theme switching.
The helpers map a token to its CSS variable name, not to a value:
export const Colors = {
primitive: {
black: "colors-primitive-black",
},
};Which is why switching theme is a variable swap — the name a component references does not change.
Not bugs, but things to expect when you read the output:
Elements are div and span. The generated markup is structural, not semantic — there is no automatic <nav>, <button> or heading level.
Custom attributes are data-* and id only. aria-* and role are not emitted.
Repeats use the runtime, not .map() — you will see msi.utils.loopOnArray rather than a JSX map, and repeated elements do not carry a React key.
Formatting is Prettier's defaults, not your project's .prettierrc.
How export works — the model.
Export your code — producing these files.
Examples — real exported components from this site.