CLI tool
kaltwrk/motion-core avatar
kaltwrk/motion-core

Motion Core: Svelte motion components you copy into your own codebase

Curated Motion Core Svelte components

583 stars17 forksSvelteMIT

At a glance

What is it?
Motion Core is a curated set of Svelte 5 motion components that are installed by a Rust CLI which copies their source into your project rather than adding a dependency, with WebGL and timeline work delegated to GSAP and OGL. It suits a team that wants to own and edit the animation code, and it asks you to accept the components as they are rather than as a versioned package.
Who is it for?
Motion Core is worth trying if you are building the kind of interface where motion carries meaning and you would rather read and edit the animation code than call a black box, because the copy-paste architecture means the component source lives in your repository and you can change it without a version bump, and because the components are built on GSAP and OGL rather than on a bespoke runtime.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 83 days ago.
What is it written in?
Mainly Svelte, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An un-library, and what that means for your dependency tree

Motion Core describes itself as more than a library, a curated collection of expressive, production-ready motion components for the experimental web. The part that matters for an engineer is the next sentence: the project does not package everything into a massive npm dependency. Instead it follows a copy-paste architecture inspired by shadcn/ui, and the project asks you to poke around the code, break things, and contribute back.

The word the project uses for itself is the Un-Library, and the reason is that you use the CLI to scaffold components directly into your codebase, with no black boxes.

The practical difference from a normal dependency is where the code lives. With a dependency, the animation source sits in your node_modules and you can only configure it through its props. With Motion Core, the component's Svelte file is a file in your repository. You read it, you edit it, and your change survives the next install because the next install does not overwrite your edit unless you ask it to. You also take on the maintenance of that code when the upstream version changes shape.

That trade is the whole decision. If the answer is that you want to own the motion code, this is the right shape. If the answer is that you want a versioned dependency with a changelog, it is the wrong shape, and the project's own framing, that it does not want a massive npm dependency, is an argument for the choice rather than a workaround for it.

The rendering work itself is not the project's own. It wraps complex WebGL and timeline-based animations into components, and the heavy lifting is done by GSAP and OGL, with the stated goal of 60fps experiences. The components are Svelte 5 native, using Runes and Snippets.

The CLI does three jobs, and one of them writes to your project

The developer workflow is two commands, and the first one is worth reading carefully because it modifies your project rather than just your node_modules.

In your SvelteKit project, the init command sets up the environment, installs the base dependencies, which the documentation names as things like clsx and tailwind-merge, and configures a motion-core.json file:

bash
npx @motion-core/cli init

Then you browse the documentation, find a component you like, and add it:

bash
npx @motion-core/cli add infinite-gallery
npx @motion-core/cli add magnetic

What that does is download the component source code and place it in your configured components directory, whose default is $lib/motion-core.

So the CLI is three things: a dependency installer, a config writer, and a source fetcher. Two of those three write into your repository. The init step adds packages to your package.json and drops a motion-core.json, and the add step drops a component file.

That is a real operational difference from installing a package, and it is worth being deliberate about it. The dependency list you end up with includes the base utilities the components expect, so a project that has its own clsx version or its own tailwind-merge configuration has to reconcile them rather than have a package manager resolve them. The motion-core.json file is where the components directory and the rest of the configuration live, which means the CLI's behaviour is inspectable and editable rather than hidden in a global config.

The npm badge in the readme points at @motion-core/cli, so the CLI is a published package with a scoped name, invoked through npx without a global install.

A monorepo where the CLI is written in Rust

The repository is a pnpm and Nx monorepo, and it houses the whole ecosystem in three parts.

packages/motion-core is the source of truth for all components. apps/docs is the documentation site and the development playground. And motion-core-cli is the Rust-based CLI tool that powers the distribution.

That third part is the interesting one, and it is why the repository root carries both a Cargo.toml and a package.json. The CLI is a Rust workspace with two crates, motion-core-cli/crates/core and motion-core-cli/crates/cli, on edition 2024, with the workspace version at 0.6.1 and the licence MIT. The dependency list is a normal Rust CLI dependency set: clap for argument parsing with derive, serde and serde_json and toml for configuration, reqwest with rustls-tls for HTTP, dialoguer for interactive prompts, indicatif for progress bars, owo-colors for terminal colour, tracing with tracing-subscriber for logging, semver for version comparison, dirs for locating configuration directories, and base64 and pathdiff for the path handling that a source-copying tool needs.

The release profile is worth noting because it says what the artefact is for. opt-level is set to z, lto is on, codegen-units is 1, symbols are stripped and panic is set to abort. That is the profile of a small, fast-starting binary that a developer runs through npx, not of a server.

So a Svelte component library ships its installer in Rust. The reason is visible in the dependency list: the CLI has to fetch files over HTTP, verify and unpack them, and prompt the user interactively, and doing that in Rust gives a single binary with no runtime installation.

Running the repository locally, and what the scripts actually do

The contributor setup is three steps, and the scripts in the root package.json make the structure clear.

Clone and install:

bash
git clone https://github.com/motion-core/motion-core.git
cd motion-core
pnpm install

Then bootstrap the workspace, which the documentation describes as generating the internal registry manifest and performing initial checks on the CLI:

bash
pnpm run workspace:bootstrap

And start the development server, where the documentation says the documentation app is the dev environment so components can be tested in real time:

bash
pnpm run dev

The playground is then at http://localhost:5173.

The script names reveal the Nx project layout. Everything web related is aliased to the same Nx target: dev, build, deploy:web, check, preview, and the registry build. The CLI has its own set: cli:check, cli:test, cli:build, cli:build:release and cli:dist. And workspace:bootstrap is the composition of two of them, the registry generation followed by a CLI check, which is why bootstrapping both generates the manifest the components are fetched from and validates that the CLI still compiles.

The three CLI development commands are also documented directly:

bash
# Check for compilation errors
pnpm run cli:check

# Build the binary
pnpm run cli:build

# Run the test suite
pnpm run cli:test

Two details in the manifest are easy to miss. There is a navigation:check script that runs a validation script over the documentation's navigation, and lint-staged runs two registry and navigation validators against the component.json files in packages/motion-core/src/lib/components, so the registry metadata is checked on commit rather than at release time.

The toolchain is pinned: pnpm at 10.33.3 as the package manager, TypeScript 5.9.3, Nx 22, eslint 9 with the Svelte plugin, prettier with the Svelte and Tailwind CSS plugins, husky for the git hooks, and svelte-check for the type check.

Where Motion Core is the wrong tool

The first limit is that there is no version to pin. A copy-paste component library has no semver contract with you, because there is no package you depend on. When upstream changes a component's API, your copy does not change with it, and there is nothing in your lockfile that tells you a version moved. The registry manifest exists, and the registry build target exists, so upstream does version its components, but the version lives in the manifest rather than in your dependency graph, and a bumped manifest does not reach a project that already copied the code.

The second is the maintenance of copied code. A component that assumes a particular tailwind configuration, or a particular gsap version, or a particular Svelte runes pattern, becomes your code to maintain. The documentation is honest that you should be able to break things, which is the appeal, and it is also the cost.

The third is that the aesthetic is the product. The stated range runs from magnetic buttons to 3D infinite galleries with cloth distortion, and the goal is stated as making high-end motion design accessible with every component crafted with feel in mind. That is a coherent point of view and it produces components that look like they belong together. It also means the components are opinionated in a way that a general-purpose UI library is not, and a design system that has its own motion language will fight them.

The fourth is the runtime weight. The heavy lifting is GSAP and OGL, and WebGL effects on a page that also has application content are a performance question for whoever owns the page. A 3D infinite gallery is a legitimate component to copy in; it is not one to enable on every route of a product.

The fifth is the ecosystem shape. The package is published under the @motion-core scope, the CLI is Rust, the components are Svelte 5, and the documentation site is the playground. A team that does not use Svelte 5 gets nothing, and a team that has standardised on one animation library across a mixed stack will end up with two.

The last point is maintenance timing. The last push to the repository was on 2026-08-01 and there are no GitHub releases, so what you copy is whatever is on the branch at the moment you copy it.

Editorial conclusion

Motion Core is worth trying if you are building the kind of interface where motion carries meaning and you would rather read and edit the animation code than call a black box, because the copy-paste architecture means the component source lives in your repository and you can change it without a version bump, and because the components are built on GSAP and OGL rather than on a bespoke runtime. It is the wrong choice if you want a dependency you can upgrade, and the wrong choice for a team that cannot accept copied source. Before you adopt it, check the three things the project tells you: that the init command writes a motion-core.json and installs base dependencies such as clsx and tailwind-merge into your project, so the CLI changes your dependency set; that the components land in a configured components directory whose default is $lib/motion-core, so the copy is going to be committed; and the maintenance picture, since the last push was on 2026-08-01, there are no GitHub releases, and the CLI itself is versioned separately in the Rust workspace at 0.6.1 while the components move through a registry manifest.

Frequently asked questions

How do I install Motion Core components in a SvelteKit project?

Run npx @motion-core/cli init to set up the environment, install the base dependencies such as clsx and tailwind-merge, and configure a motion-core.json file. Then add a component with npx @motion-core/cli add, for example npx @motion-core/cli add infinite-gallery, which downloads the source into your components directory, $lib/motion-core by default.

Does Motion Core add a component to my package.json?

It adds the component source code to your project rather than adding it as a dependency. The init command installs base dependencies such as clsx and tailwind-merge and writes a motion-core.json, and the add command places the component file in your configured components directory, whose default is $lib/motion-core.

What is written in Rust in the Motion Core repository?

The CLI tool is. The motion-core-cli directory holds a Rust workspace with two crates, core and cli, on edition 2024 with the workspace version at 0.6.1, built with clap, reqwest over rustls-tls, serde, dialoguer, indicatif and tracing, and released with a size-optimised profile using lto and panic abort.

Official sources

  1. Issues
  2. kaltwrk/motion-core on GitHub
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kaltwrk-motion-core.svg)](https://hysenlabs.com/projects/kaltwrk-motion-core)

Was this useful?