- Reusable Three.js animations
- Built with React Three Fiber
- Interactive component previews
- Individual documentation pages
- Central component registry
- Support for custom shaders and effects
- Designed to make adding new animations simple
- React
- TypeScript
- Vite
- Three.js
- React Three Fiber
- Drei
- React Router
src/
├── components/
│ └── Floating/
│ ├── Floating.tsx
│ └── index.ts
│
├── demos/
│ └── FloatingDemo.tsx
│
├── pages/
│ ├── HomePage.tsx
│ ├── ComponentsPage.tsx
│ └── ComponentPage.tsx
│
├── ui/
│
├── data/
│ └── components.ts
│
├── hooks/
│
└── shaders/
Contains the reusable animations and effects that make up the Animythos library.
These components should not depend on the documentation website.
Contains scenes used to demonstrate library components.
A demo can contain cameras, lighting, objects, environments, controls, and other elements needed to showcase the component.
Contains the pages used by the showcase website.
Contains reusable UI components used by the website itself.
Contains component metadata and the central component registry.
Contains reusable React and Three.js hooks.
Contains reusable GLSL shader code.
Clone the repository:
git clone https://github.com/YOUR_USERNAME/animythos.gitEnter the project:
cd animythosInstall dependencies:
npm installStart the development server:
npm run devThe application will normally be available at:
http://localhost:5173
Animations in Animythos consist of two main parts:
Reusable component
↓
Demo
↓
Component registry
↓
Website
For example:
Floating.tsx
↓
FloatingDemo.tsx
↓
components.ts
↓
/components/floating
Create a new folder inside:
src/components/
For example:
src/components/Rotation/
Add the component:
Rotation/
├── Rotation.tsx
└── index.ts
Example:
import type { ReactNode } from "react";
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import type { Group } from "three";
interface RotationProps {
children: ReactNode;
speed?: number;
}
function Rotation({
children,
speed = 1,
}: RotationProps) {
const groupRef = useRef<Group>(null);
useFrame((_, delta) => {
if (!groupRef.current) return;
groupRef.current.rotation.y += delta * speed;
});
return (
<group ref={groupRef}>
{children}
</group>
);
}
export default Rotation;Export it from:
src/components/Rotation/index.ts
export { default as Rotation } from "./Rotation";Create a demo inside:
src/demos/
For example:
src/demos/RotationDemo.tsx
import { Canvas } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";
import { Rotation } from "../components/Rotation";
function RotationDemo() {
return (
<div style={{ width: "100%", height: "400px" }}>
<Canvas camera={{ position: [0, 0, 4] }}>
<ambientLight intensity={1.5} />
<directionalLight
position={[3, 3, 3]}
intensity={2}
/>
<Rotation speed={1}>
<mesh>
<boxGeometry />
<meshStandardMaterial />
</mesh>
</Rotation>
<OrbitControls />
</Canvas>
</div>
);
}
export default RotationDemo;The demo belongs to the website and should not contain reusable component logic.
The component registry is located at:
src/data/components.ts
Import the new demo:
import RotationDemo from "../demos/RotationDemo";Then add a registry entry:
{
slug: "rotation",
name: "Rotation",
description: "Continuously rotates any 3D object.",
category: "Animation",
demo: RotationDemo,
}The registry may then look like:
export const components: ComponentInfo[] = [
{
slug: "floating",
name: "Floating",
description: "Adds a smooth floating animation to any 3D object.",
category: "Animation",
demo: FloatingDemo,
},
{
slug: "rotation",
name: "Rotation",
description: "Continuously rotates any 3D object.",
category: "Animation",
demo: RotationDemo,
},
];Once registered, the component should automatically appear on:
/components
Its individual page should become available at:
/components/rotation
You should not need to modify ComponentPage.tsx.
The component registry is the central source of truth for the showcase website.
Each entry currently follows this structure:
export interface ComponentInfo {
slug: string;
name: string;
description: string;
category: ComponentCategory;
demo: ComponentType;
}Used to generate the component URL.
slug: "particle-field"becomes:
/components/particle-field
The displayed component name.
name: "Particle Field"A short explanation of what the component does.
Used to organize components.
Current categories include:
Animation
Particles
Shaders
Camera
Background
The React component used as the live preview.
demo: ParticleFieldDemoComponents should be reusable rather than tied to one specific object.
Prefer:
<Floating>
<MyModel />
</Floating>over:
<FloatingCube />Expose useful configuration through props:
<Floating
speed={2}
amplitude={0.5}
>
<MyModel />
</Floating>Try to keep:
- reusable logic inside
components - showcase-specific logic inside
demos - website UI inside
ui - shared hooks inside
hooks - reusable shader code inside
shaders
GitHub does not run React or Three.js directly inside README files.
The easiest way to show Animythos in motion is therefore an animated GIF.
Create:
public/
└── readme/
└── animythos-demo.gif
Then the README can display it with:
<p align="center">
<img
src="./public/readme/animythos-demo.gif"
alt="Animythos component showcase"
width="800"
/>
</p>A good future GIF could quickly cycle through several components:
Floating
↓
Particles
↓
Dissolve
↓
Shader effect
↓
Animythos
This gives visitors an immediate visual explanation of the project before they read the documentation.
Animythos is currently under development.
Initial focus:
- Build the component showcase
- Establish the reusable component architecture
- Add the first animation components
- Add usage and source-code documentation
- Expand into particles, shaders, camera effects, and backgrounds