A 3D landing page built with Typescript, Vite, react-three-fiber (r3f) and Blender.
make
1 with:
Use Make to streamline local development for this project (like a task-runner with straightforward rules). Launch project locally via node
with pnpm
(1), docker
with compose
plugin (2), or kubectl
with a configured Kubernetes cluster (3). Note that these rules are tailored for local use and aren't intended for production scenarios. For example:
make node.all
make docker.all
Simple application lifecycle management with these rules:
node.all
: Installs dependencies, builds the project, and starts it.node.install
: Install project dependencies using pnpm.node.dev
: Start the project in development mode using pnpm.node.build
: Build the project.node.start
: Start the project in preview mode.
Multi-service and flexible application lifecycle management with docker compose
using these rules:
docker.all
: Build images, pull the latest versions, and start containers.docker.clean
: Stop containers, remove images, and clean up volumes.docker.build
: Build compose images.docker.pull
: Pull the latest image for a specific service.docker.up
: Start compose containers in detached mode.docker.down
: Stop compose containers for a specific service.docker.down.images
: Stop containers and remove associated images.docker.down.volumes
: Stop containers and delete volumes.docker.ps
: List containers for a specific service in JSON format.docker.top
: Display running processes of a specific container.docker.events
: Stream Docker events for a specific service in JSON format.docker.logs
: Stream logs for containers or a specific service.docker.exec
: Execute a command inside a specific container. Require SVC, CMD values.docker.cp.from
: Copy files from a container to the host. Require SVC, SRC, DST values.docker.cp.to
: Copy files from the host to a container. Require SVC, SRC, DST values.
Docker rules can optionally take a SVC parameter to use command on a specific service.
Manage and monitor Kubernetes resources using Kustomize with these rules:
k8s.apply
: Apply Kubernetes resources defined indeploy/
.k8s.delete
: Delete Kubernetes resources defined indeploy/
.k8s.get
: Retrieve and display Kubernetes resources fromdeploy/
.k8s.describe
: Describe Kubernetes resources fromdeploy/
.k8s.logs
: Stream logs from Kubernetes resources indeploy/
.
Repository contains javascript/typescript, static assets and configuration resources for a Vite application.
Vite
uses a static HTML file as entrypoint (/index.html
) and loads modules in javascript or typescript format. In development mode, Vite
starts a node server to watch change in /src
directory and provide hot-reload functionality. In production mode, there are two steps. At first, you need to use Vite
to build your application into static content in a /dist
directory. Then you serve it with an express-like server (or any node-compatible environment) on a dedicated server or through any static content delivery service like Netlify
, Cloudflare
, Vercel
, etc...
Static resources in /dist
directory are bundled, minified and optimized Javascript
assets built by a typescript-compiler from source code containing typescript-react components. Typescript
adds a strong-typing system which improves drastically code completion and error detection from a developer perspective. Components are written with React
because even if, nowadays, "vanilla" javascript has built-in high-level functionalities, React
became a lot like node itself: it is not only used for the reason that it provides great benefits but rather than it has a rich and strong ecosystem. Various node libraries offers built-in integration for react and numerous libraries are even built-on react hooks or JSX
functionalities. JSX
(or TSX
for typescript) is the format used in react ecosystem to write HTML
templates.
Styles are directly written in components thanks to Emotion
"css-in-js" engine (except for those generated by create-vite template). It integrates flawlessly with existing css-component libraries like Tailwindcss
. You could use react-ui-component libraries such as Mantine
(or more opinionated MaterialUI
) to import ready-to-use components for layouts, form inputs, theming (dark, light, others), notification system... Mantine
components are fully customizable through Emotion
API. Global CSS
directives should be avoided to ensure maintainability (!important directives notably).
For 3D integration, three.js is a very known library in javascript ecosystem. It provides a wrapper on WebGL to create scenes, cameras, meshes in web canvas. Nevertheless it is still complex to design performant 3D interfaces with a "simple" library. You should use react-three-fiber ecosystem as a framework to build such a system. It provides react components with out-of-the-box functionalities through libraries such as @react-three/fiber
, @react-three/drei
(++), @react-three/a11y
or @react-three/postprocessing
. Thus it leverages react hydration capabilities to provide dynamic, flexible and very efficient interfaces.
Use node
/pnpm
to start and use project locally. You could like to use docker compose
to integrate other services with a Vite
application, manage multiple applications or to build a micro-service architecture. However micro-service architecture depends on complex interconnectivity between components of an ecosystem, thus requires intensive proxying or a service-mesh based architecture. Kubernetes helps to leverage this kind of architecture.
- Configuration related to repository or application lifecycle lies on repository root:
- repository configuration (
/.gitignore
,/.gitattributes
), - application lifecycle management (
/Makefile
,/Dockerfile.{dev,prod}
,/docker-compose.yaml
), - application configuration (
/package.json
,/tsconfig*.json
,/vite.config.ts
and/.eslintrc.cjs
), - application entrypoint (
/index.html
).
- repository configuration (
- Contains application source code in
*.tsx
format,- application code entrypoint (root react element) in
/src/main.tsx
, - application main component (app component) in
/src/App.tsx
, - application components in
/src/components/**/*.tsx
(such as@react-three/gltfjsx
components6), - internal static assets in
/src/assets/**/*
(such as*.svg
and*.glb
3D models).
- application code entrypoint (root react element) in
- Contains public static assets, i.e. statically served to users (contrarly to
/src/assets/
directory, only accessible internally).- application favicon (
/public/palm-tree-icon.png
).
- application favicon (
- Contains static resources to serve application content in production,
- HTML and public resources in
/dist/**/*
, - javascript and internal assets in
/dist/assets/**/*
.
- HTML and public resources in
- Contains
Github Actions
workflows to build and push application image on registry (here, ghcr.io) onpush/tags
events,- pipeline in
/.github/workflows/ci.yaml
(based onDocker
public actions).
- pipeline in
- Contains
Kubernetes
YAML
manifests to deploy application in production,- application manifests are stored in the same repository as the source code,
- infrastructure manifests live on their own repository-ies,
- Contains sample Kubernetes resources for a deployment,
- a clusterIP service,
- a secured ingress serving one host,
- a deployment for a pod with one container based on image hosted on private registry.
Node is an execution environment for javascript code and pnpm is a modern package manager for npm packages.
- Install
node
for your os-family from nodesources:
- Debian based
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - &&\
sudo apt-get install -y nodejs
- Redhat based
curl -fsSL https://rpm.nodesource.com/setup_lts.x | sudo bash -
- Install
pnpm
package manager globally withnpm
:
npm i -g pnpm
- Install application dependencies locally:
pnpm i
- Run application in development mode (with hot-reloading functionality):
pnpm dev
K3d is a wrapper around K3s Kubernetes distribution to run a Kubernetes cluster with Docker containers rather than virtual machines. K3s is a lightweight, flexible and ready-to-use distribution to create Kubernetes nodes. It offers ability to run schedulable server nodes or agent nodes, thus allowing setup from single-node cluster to high-availability cluster through a various range of scenarios. It has multiple pre-installed components as an internal core-dns server, a traefik reverse-proxy, a local-path storage provider and a metrics server, which can all be disabled on installation. K3d runs each K3s nodes and each internal load balancers services as a container, providing a very straightforward local developement or automated testing environment.
- Install
k3d
with bash script from rancher's repository:
curl -fsSL https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
- Create a cluster7 with 3 servers nodes and 2 agents nodes (optional) with
k3d
cli:
k3d cluster create my-cluster --servers 3 --agents 2 -p "8080:80@loadbalancer" -p "8443:443@loadbalancer"
- Verify that nodes are up and running:
kubectl get nodes
- Build a container image based on
Dockerfile.prod
and tag it with your username:
docker build -t gmarcha/vite-app:latest -t gmarcha/vite-app:0.0.1 -f Dockerfile.prod .
-
Then update container image name and tag in
/deploy/deployment.yaml
(or build your image tag based on used tag) and remove image pull secrets configuration. -
Update host value from
gmarcha.com
tovite.localhost
in ingress ressource into/deploy/ingress.yaml
(or redirect existing domain to localhost) and remove tls-related configuration. -
Apply Kubernetes manifests in
/deploy
directory with kustomize:
kubectl apply -k deploy/
- Monitor pod status with kubectl and wait its readiness:
kubectl get pod -k deploy/
-
Then access application with curl or directly in browser at http://vite.localhost:8080
-
Delete Kubernetes resources contained in manifests in
/deploy
directory with kustomize again:
kubectl delete -k deploy/
- Delete
k3d
cluster:
k3d cluster delete my-cluster
-
Download free 3D models in GLTF/GLB format or export/convert models from blender.
-
Use
npx
command with a docker container if node is not installed locally (optional):
echo "alias npx='docker run -it --rm ${PWD}:/app -w /app node npx'" | tee -a ~/.bashrc > /dev/null
- Use
gltfjsx
command withnpx
to convert fromglb
file tojsx
file (with shadow projection):
npx gltfjsx -s model.glb
- Or use
gltfjsx
command to convert fromglb
file totsx
file:
npx gltfjsx -st model.glb
Typescript is a superset of JavaScript that introduces static typing (so code completion), enhancing code reliability and maintainability. Code quality is highly improved, reducing runtime errors. Typescript sources are compiled into Javascript code. Javascript remains the core scripting language for web development, powering interactive web applications.
- Documentation: Typescript Docs
- Documentation: Javascript MDN Web Docs
Vite is a modern build tool and development server designed to optimize frontend development workflows. It's particularly well-suited for building simple single-page applications quickly with a strong emphasize on fast development. Moreover Vite
is non-opinionated about what component library you are using: it works out-of-the-box with Vue, React, Preact, Svelte and more! It also works with both typescript and javascript. It can use SWC rust-based compiler for typescript-react projects.
- Documentation: Vite Getting Started
- Github repository: @vitejs/plugin-react-swc
React is a widely adopted Javascript library for creating interactive user interfaces. It employs a component-based architecture, allowing developers to build and to shape UI with reusable components efficiently. React is particularly optimized to hydrate components based on data change, handled through built-in or custom hooks. In my opinion, JSX/TSX templating system is more developer friendly than a pure templating system such as Svelte/Vue, which has non-trivial caveats in complex situations. It has a vast ecosystem ranging from a wide range of frameworks (Next.js, Remix, Blitz) with various design standard to a plenty of react-ui-component libraries (MaterialUI, Mantine, ChakraUI) with different integration methods.
- Documentation: React Documentation
- Documentation: Next Documentation
- Documentation: Remix Documentation
- Documentation: Mantine Documentation
- Documentation: ChakraUI Documentation
Three.js is a popular Javascript library simplifying 3D graphics and animations in web browsers. It allows to create simple objects based on WebGL features. Those objects are scenes, meshes, cameras, lights, physics and effects for example. Nowadays you can even use it to create advanced graphics based on ray-casting, to import 3D models into web application or to render VR environment. Three still has a difficult learning curve and is very complex to implement clean data changes and user interactions.
- Documentation: Three.js Documentation
- Examples: Three.js Examples
React-Three-Fiber leverages the power of React and Three.js, providing a declarative approach to integrating 3D graphics into React applications. It allows to write three objects in a JSX or TSX fashion, thus allowing users to create complex scenes tightly integrated with react-components lifecycle. Additionally react-three project supplies plenty of libraries to handle various use-cases: @react-three/fiber
for basic hooks and components, @react-three/drei
for advanced components, @react-three/a11y
for accesibility and interactivity, @react-three/postprocessing
for astonishing and dead-simple render effects, @react-three/gltfjsx
to convert 3D model from *.glb
to *.{j,t}sx
components, @react-three/xr
to handle VR/AR events, and a lot more...
- Documentation: @react-three/fiber Documentation
- Github repository: @react-three/drei Documentation
- Github repository: @react-three/a11y Documentation
- Github repository: @react-three/postprocessing Documentation
- Github repository: @react-three/gltfjsx Documentation
- Github repository: @react-three/xr Documentation
- Examples: React-Three-Fiber Examples
Blender is a versatile open-source 3D creation suite suitable for a wide range of tasks, including modeling, animating, rendering, and more. It can be harnessed to model complex 3D scenes with sculpting, texture shading, or even geometry-nodes based tools. Then it has the capability to export 3D models, materials and animation sequences in a specific format to a future integration in a web, desktop or game application. It can also be utilized to render content directly in Blender tool suite and export images, animated content, videos.
- Documentation: Blender Manual 3.6.1
- Tutorials: Blender Youtube Playlist
Make is a versatile build automation tool employing "Makefiles" to define tasks and dependencies. It helps streamline project workflows and build processes. Although more modern build tools exists, Make serves as a very lightweight task-runners to bootstrap projects or "glue" tasks in a local environment. It replaces json-scripts
in language-agnostic environment.
- Documentation: GNU Make Manual
Docker is a widely-used platform for creating, deploying, and managing containers. Containers provide a consistent and isolated environment for applications, ensuring that they run reliably across various environments. This is particularly useful for flexible local development practices (in comparison to development in virtual machines).
- Documentation: Docker Documentation
- Documentation: Dockerfile Reference
- Container registry: Dockerhub Registry
Kubernetes is an open-source container orchestration platform that automates the deployment and management of containerized applications with a declarative approach. It enables efficient management of computing resources, simplifies tasks such as load balancing/scaling/rollouts, enhances observability and supports multi-cloud architectures. Such requirements are handled with cloud-native service mesh (Istio, Linkerd) and multi-cluster control planes (Karmada, Kubesphere) for example. For managing Kubernetes application, there are Kustomize and Helm. Kustomize offers ability to merge custom patches with existing Kubernetes manifests, thus providing a lightweight overlay configuration system. It also avoids the need to fork repository when deploying application based on non-owned manifests. On the other hand, Helm is the Kubernetes package manager. It allows to package various Kubernetes resources under a chart, easing application deployment and customization with Go templating system. ArtifactHub is a Kubernetes package registry to register Helm repositories or distribute Helm charts and other Kubernetes resources.
- Documentation: Kubernetes Documentation
- Documentation: Kubectl and Kustomize Documentation
- Documentation: Helm Documentation
- Kubernetes registry: Artifact Hub
- Add animation to
*.glb
3D models. - Migrate from
vite
tonextjs
.
Footnotes
-
sudo apt install make
,sudo dnf install make
, or building from source for non-managed distros. ↩ -
follow instructions depending on your os-family, then install pnpm globally with node default package manager, npm:
npm -g i pnpm
. ↩ -
follow instructions for server (and not desktop) version depending on your distribution, then follow post-install instructions. ↩
-
install kubectl, install k3d to run a local cluster with docker (configure k3d). ↩
-
replace
.spec.template.spec.containers.[0].image
by your own image name and tag in/deploy/deployment.yaml
(be careful to create secret containing credentials - username, password - for private registry). ↩ -
use
npx gltfjsx -ts <model.glb>
to create TSX component (with shadows) from gltf model. ↩ -
k3s server nodes are schedulable by default (see documentation) and k3s support single-node server cluster (be careful, k3s doesn't support adding servers to single-node setup). ↩