├── screenshot_export_vanillajs.png
├── public
├── 3d-models
│ └── planet
│ │ └── scene.splinecode
└── vite.svg
├── counter.js
├── .gitignore
├── package.json
├── javascript.svg
├── main.js
├── style.css
├── README.md
└── index.html
/screenshot_export_vanillajs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mandrasch/spline-selfhosted/HEAD/screenshot_export_vanillajs.png
--------------------------------------------------------------------------------
/public/3d-models/planet/scene.splinecode:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mandrasch/spline-selfhosted/HEAD/public/3d-models/planet/scene.splinecode
--------------------------------------------------------------------------------
/counter.js:
--------------------------------------------------------------------------------
1 | export function setupCounter(element) {
2 | let counter = 0
3 | const setCounter = (count) => {
4 | counter = count
5 | element.innerHTML = `count is ${counter}`
6 | }
7 | element.addEventListener('click', () => setCounter(counter + 1))
8 | setCounter(0)
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "spline-selfhosted",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "vite": "^4.4.5"
13 | },
14 | "dependencies": {
15 | "@splinetool/runtime": "^0.9.493",
16 | "@splinetool/viewer": "^0.9.493"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/javascript.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | import './style.css'
4 |
5 | // Import spline scene via vanillajs runtime:
6 |
7 | import { Application } from '@splinetool/runtime';
8 |
9 | // make sure you have a canvas in the body
10 | const canvas = document.getElementById('canvas3d');
11 |
12 | // start the application and load the scene (selfhosted)
13 | const spline = new Application(canvas);
14 | spline.load('/3d-models/planet/scene.splinecode');
15 |
16 | // TODO: does not work?
17 | spline.setBackgroundColor('red');
18 |
19 | // import spline viewer webcomponent
20 | import { SplineViewer } from '@splinetool/viewer';
21 |
22 | // Vite scaffold demo code:
23 | // import javascriptLogo from './javascript.svg'
24 | // import viteLogo from '/vite.svg'
25 | // import { setupCounter } from './counter.js'
26 |
27 | // document.querySelector('#app .vite-demo-content').innerHTML = `
28 | //
29 | //
30 | //
31 | //
32 | //
33 | //
34 | //
35 | //
Hello Vite!
36 | //
37 | //
38 | //
39 | //
40 | // Click on the Vite logo to learn more
41 | //
42 | //
43 | // `
44 |
45 | // setupCounter(document.querySelector('#counter'))
46 |
47 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | -webkit-text-size-adjust: 100%;
15 | }
16 |
17 | a {
18 | font-weight: 500;
19 | color: #646cff;
20 | text-decoration: inherit;
21 | }
22 | a:hover {
23 | color: #535bf2;
24 | }
25 |
26 | body {
27 | margin: 0;
28 | display: flex;
29 | place-items: center;
30 | min-width: 320px;
31 | min-height: 100vh;
32 | }
33 |
34 | h1 {
35 | font-size: 3.2em;
36 | line-height: 1.1;
37 | }
38 |
39 | #app {
40 | max-width: 1280px;
41 | margin: 0 auto;
42 | padding: 2rem;
43 | text-align: center;
44 | }
45 |
46 | .logo {
47 | height: 6em;
48 | padding: 1.5em;
49 | will-change: filter;
50 | transition: filter 300ms;
51 | }
52 | .logo:hover {
53 | filter: drop-shadow(0 0 2em #646cffaa);
54 | }
55 | .logo.vanilla:hover {
56 | filter: drop-shadow(0 0 2em #f7df1eaa);
57 | }
58 |
59 | .card {
60 | padding: 2em;
61 | }
62 |
63 | .read-the-docs {
64 | color: #888;
65 | }
66 |
67 | button {
68 | border-radius: 8px;
69 | border: 1px solid transparent;
70 | padding: 0.6em 1.2em;
71 | font-size: 1em;
72 | font-weight: 500;
73 | font-family: inherit;
74 | background-color: #1a1a1a;
75 | cursor: pointer;
76 | transition: border-color 0.25s;
77 | }
78 | button:hover {
79 | border-color: #646cff;
80 | }
81 | button:focus,
82 | button:focus-visible {
83 | outline: 4px auto -webkit-focus-ring-color;
84 | }
85 |
86 | @media (prefers-color-scheme: light) {
87 | :root {
88 | color: #213547;
89 | background-color: #ffffff;
90 | }
91 | a:hover {
92 | color: #747bff;
93 | }
94 | button {
95 | background-color: #f9f9f9;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # spline-selfhosted
2 |
3 | - demo repository to show selfhosting of spline 3D scene (exports)
4 |
5 | Two approaches used:
6 |
7 | - vanillajs runtime (https://www.npmjs.com/package/@splinetool/runtime)
8 | - spline-viewer web component (https://www.npmjs.com/package/@splinetool/viewer)
9 |
10 | Demo:
11 |
12 | - https://spline-selfhosted.vercel.app/ ([GDPR check](https://webbkoll.dataskydd.net/de/results?url=http%3A%2F%2Fspline-selfhosted.vercel.app%2F))
13 |
14 | ## Goals
15 |
16 | - [x] GDPR-compatibility (no 3rd party connections / no cookies), checked with https://webbkoll.dataskydd.net/de/results?url=http%3A%2F%2Fspline-selfhosted.vercel.app%2F
17 | - [ ] vanillajs: transparent background -> setBackgroundColor()?
18 | - [ ] vanillajs: Follow mouse cursor
19 | - [ ] vanillajs: Use click events --> Handling events outside of Spline (https://docs.spline.design/77c32288501a479fa8bc5e787f1e0878)
20 | - [ ] vanillajs: Use preload? https://www.npmjs.com/package/@splinetool/runtime#preloading-your-scene
21 |
22 | ## Local setup
23 |
24 | ```
25 | npm install
26 | npm run dev
27 | ```
28 |
29 | ## How was this created?
30 |
31 | Spline offers several ways to export code, see: [Exporting as Code
32 | ](https://docs.spline.design/77c32288501a479fa8bc5e787f1e0878). There is also a Web Component available:
33 | [spline-viewer](https://viewer.spline.design/).
34 |
35 | First, we scaffold a new vite project with vanillajs:
36 |
37 | ```bash
38 | # https://vitejs.dev/guide/#scaffolding-your-first-vite-project
39 | npm create vite@latest . -- --template vanilla
40 | ```
41 |
42 | ### spline runtime (vanillajs)
43 |
44 | 1. Install it:
45 |
46 |
47 | ```bash
48 | # https://www.npmjs.com/package/@splinetool/runtime
49 | npm install @splinetool/runtime
50 | ```
51 |
52 | 2. Export spline scene
53 |
54 | Use "Download bundled zip (Web content)" here:
55 |
56 | 
57 |
58 | Unzip it and place the `scene.splinecode` file into `public/3d-models`.
59 |
60 | 3. Add `