new 3JS Design

This commit is contained in:
2025-09-12 20:29:49 +02:00
parent 17e50d5978
commit ded5997000
6 changed files with 1030 additions and 0 deletions

BIN
3js/audio/stalker.mp3 Normal file

Binary file not shown.

552
3js/background.js Normal file
View File

@@ -0,0 +1,552 @@
import * as THREE from "three";
import { FBXLoader } from "three/addons/loaders/FBXLoader.js";
import { TGALoader } from "three/addons/loaders/TGALoader.js";
(() => {
if (window.__threePS1Campfire) return;
window.__threePS1Campfire = true;
const MODEL_URL = "https://seppjm.com/3js/models/scene.fbx";
const NORMALIZE_SCALE = false;
const USE_FOG = true;
const PS1_SCALE = 3;
const COLOR_LEVELS = 32;
const USE_DITHER = true;
const VERTEX_SNAP_PIXELS = 0.75;
const FIRE_POS = new THREE.Vector3(
2885.090654499771,
5.937671631541306,
-2843.489246932181
);
const CAM_POS = new THREE.Vector3(
3280.98691276581,
386.84586301208896,
-2012.4527013816644
);
const CAM_ROT_DEG = { yaw: 395.51276597880525, pitch: 2.7272791048226543 };
const CAM_FOV = 90;
const FIRE_SPRITE_SIZE = 150.0;
const FIRE_HEIGHT_OFFSET = 0.25;
const FIRE_MAIN_INTENSITY = 2.2;
const FIRE_SUB_INTENSITY = 1.0;
const FIRE_MAIN_DISTANCE = 12000;
const FIRE_SUB_DISTANCE = 6000;
const FIRE_DECAY = 1.2;
const footer = document.querySelector("footer");
const canvas = document.createElement("canvas");
canvas.id = "three-bg";
Object.assign(canvas.style, {
position: "fixed",
inset: "0",
width: "100vw",
height: "100vh",
display: "block",
zIndex: "0",
pointerEvents: "none",
clipPath: "inset(0 0 var(--bg-clip-bottom, 0px) 0)",
WebkitClipPath: "inset(0 0 var(--bg-clip-bottom, 0px) 0)",
opacity: "0",
transition: "opacity 1400ms ease",
imageRendering: "pixelated",
});
document.body.prepend(canvas);
function updateFooterClip() {
const fadeLen = 140;
const rect = footer?.getBoundingClientRect();
if (!rect) {
canvas.style.setProperty("--bg-clip-bottom", "0px");
canvas.style.maskImage = "none";
canvas.style.WebkitMaskImage = "none";
return;
}
const overlap = Math.max(0, innerHeight - rect.top);
const clip = Math.max(0, overlap - fadeLen);
canvas.style.setProperty("--bg-clip-bottom", `${clip}px`);
if (overlap > 0) {
const grad = `linear-gradient(to bottom, black 0%, black calc(100% - ${fadeLen}px), transparent 100%)`;
canvas.style.maskImage = grad;
canvas.style.WebkitMaskImage = grad;
} else {
canvas.style.maskImage = "none";
canvas.style.WebkitMaskImage = "none";
}
}
addEventListener("scroll", updateFooterClip, { passive: true });
addEventListener("resize", updateFooterClip);
new ResizeObserver(updateFooterClip).observe(document.body);
if (footer) new ResizeObserver(updateFooterClip).observe(footer);
updateFooterClip();
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: false,
alpha: true,
powerPreference: "high-performance",
});
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.NoToneMapping;
renderer.shadowMap.enabled = false;
renderer.setPixelRatio(1);
renderer.setClearColor(0x000000, 0);
let lowW = 0,
lowH = 0,
rt = null;
const postScene = new THREE.Scene();
const postCam = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
const postMat = new THREE.ShaderMaterial({
uniforms: {
tDiffuse: { value: null },
uLowRes: { value: new THREE.Vector2(1, 1) },
uLevels: { value: COLOR_LEVELS },
uDither: { value: USE_DITHER ? 1 : 0 },
uTime: { value: 0.0 },
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = (position.xy + 1.0) * 0.5;
gl_Position = vec4(position.xy, 0.0, 1.0);
}
`,
fragmentShader: `
precision mediump float;
uniform sampler2D tDiffuse;
uniform vec2 uLowRes;
uniform int uLevels;
uniform int uDither;
uniform float uTime;
varying vec2 vUv;
float hash(vec2 p) {
p = fract(p * vec2(123.34, 345.45));
p += dot(p, p + 34.345);
return fract(p.x * p.y);
}
vec3 quantize(vec3 c, vec2 pix) {
float L = float(uLevels);
float t = (uDither == 1) ? (hash(pix + uTime) - 0.5) : 0.0;
vec3 q = floor(clamp(c + t / L, 0.0, 1.0) * (L - 1.0) + 0.5) / (L - 1.0);
return q;
}
void main() {
vec2 p = vUv * uLowRes;
vec2 uv = (floor(p) + 0.5) / uLowRes;
vec3 col = texture2D(tDiffuse, uv).rgb;
col = quantize(col, p);
gl_FragColor = vec4(col, 1.0);
}
`,
depthTest: false,
depthWrite: false,
});
postScene.add(new THREE.Mesh(new THREE.PlaneGeometry(2, 2), postMat));
function resizeRenderer() {
const w = innerWidth,
h = innerHeight;
lowW = Math.max(1, Math.floor(w / PS1_SCALE));
lowH = Math.max(1, Math.floor(h / PS1_SCALE));
renderer.setSize(w, h, false);
if (rt) rt.dispose();
rt = new THREE.WebGLRenderTarget(lowW, lowH, {
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
depthBuffer: true,
stencilBuffer: false,
type: THREE.UnsignedByteType,
samples: 0,
});
postMat.uniforms.uLowRes.value.set(lowW, lowH);
}
resizeRenderer();
const scene = new THREE.Scene();
scene.environment = null;
scene.fog = USE_FOG ? new THREE.FogExp2(0x0b1020, 0.02) : null;
const camera = new THREE.PerspectiveCamera(
CAM_FOV,
innerWidth / innerHeight,
0.005,
5000
);
camera.position.copy(CAM_POS);
const BASE_YAW = THREE.MathUtils.degToRad(
((CAM_ROT_DEG.yaw % 360) + 360) % 360
);
const BASE_PITCH = THREE.MathUtils.degToRad(CAM_ROT_DEG.pitch);
camera.rotation.set(BASE_PITCH, BASE_YAW, 0, "YXZ");
camera.updateProjectionMatrix();
const MAX_YAW_DELTA = THREE.MathUtils.degToRad(6);
const MAX_PITCH_DELTA = THREE.MathUtils.degToRad(4);
let aimYaw = BASE_YAW,
aimPitch = BASE_PITCH;
let curYaw = BASE_YAW,
curPitch = BASE_PITCH;
addEventListener(
"pointermove",
(e) => {
const nx = (e.clientX / innerWidth) * 2 - 1;
const ny = (e.clientY / innerHeight) * 2 - 1;
aimYaw = BASE_YAW - nx * MAX_YAW_DELTA;
aimPitch = BASE_PITCH + ny * MAX_PITCH_DELTA;
},
{ passive: true }
);
function updateCameraHover(dt) {
const smooth = 1.0 - Math.pow(0.2, dt * 60);
curYaw += (aimYaw - curYaw) * smooth;
curPitch += (aimPitch - curPitch) * smooth;
camera.rotation.set(curPitch, curYaw, 0, "YXZ");
}
scene.add(new THREE.HemisphereLight(0xb0c8ff, 0x0b1020, 0.28));
const sun = new THREE.DirectionalLight(0xffffff, 0.6);
sun.position.set(3, 5, 4);
scene.add(sun);
const basePath = MODEL_URL.slice(0, MODEL_URL.lastIndexOf("/") + 1) || "/";
const manager = new THREE.LoadingManager();
manager.addHandler(/\.tga$/i, new TGALoader(manager));
const loader = new FBXLoader(manager);
loader.setResourcePath(basePath);
let model,
mixer,
sceneRadius = 100;
const patchedMaterials = new Set();
const perFrame = [];
function ps1ifyMaterials(root) {
root.traverse((n) => {
if (!n.isMesh) return;
const src = n.material;
const mats = (Array.isArray(src) ? src : [src]).filter(Boolean);
const newMats = mats.map((m) => {
const p = {
color:
m.color && m.color.isColor
? m.color.clone()
: new THREE.Color(0xffffff),
map: m.map || null,
transparent: false,
alphaTest:
(m.alphaTest ?? 0.0) > 0
? m.alphaTest
: m.map?.format === THREE.RGBAFormat
? 0.5
: 0.0,
side: THREE.DoubleSide,
};
const lm = new THREE.MeshLambertMaterial(p);
["map", "emissiveMap", "aoMap", "specularMap"].forEach((k) => {
const tex = lm[k];
if (tex) {
tex.generateMipmaps = false;
tex.minFilter = THREE.NearestFilter;
tex.magFilter = THREE.NearestFilter;
tex.anisotropy = 0;
tex.needsUpdate = true;
}
});
lm.depthWrite = true;
lm.depthTest = true;
lm.dithering = false;
lm.polygonOffset = true;
lm.polygonOffsetFactor = -0.5;
lm.polygonOffsetUnits = 1.0;
lm.onBeforeCompile = (shader) => {
shader.uniforms.uResolution = {
value: new THREE.Vector2(innerWidth, innerHeight),
};
shader.uniforms.uSnapPixels = { value: VERTEX_SNAP_PIXELS };
shader.vertexShader = shader.vertexShader.replace(
/void\s+main\s*\(\)\s*\{/,
"uniform vec2 uResolution;\nuniform float uSnapPixels;\nvoid main(){"
);
if (VERTEX_SNAP_PIXELS > 0) {
shader.vertexShader = shader.vertexShader.replace(
"#include <project_vertex>",
`
#include <project_vertex>
vec2 ndc = gl_Position.xy / gl_Position.w;
vec2 pix = (ndc * 0.5 + 0.5) * uResolution;
pix = floor(pix / uSnapPixels) * uSnapPixels;
vec2 ndc2 = (pix / uResolution) * 2.0 - 1.0;
gl_Position.xy = ndc2 * gl_Position.w;
`
);
}
lm.userData._ps1Shader = shader;
patchedMaterials.add(lm);
};
return lm;
});
n.material = Array.isArray(src) ? newMats : newMats[0];
});
}
function autoFogFor(target) {
if (!USE_FOG) return;
const box = new THREE.Box3().setFromObject(target);
const size = box.getSize(new THREE.Vector3());
sceneRadius = Math.max(size.x, size.y, size.z) * 0.5 || 100;
const k = 0.03;
const density = Math.min(0.06, Math.max(0.000005, k / (sceneRadius || 1)));
scene.fog = new THREE.FogExp2(0x0b1020, density);
}
loader.load(
MODEL_URL,
(fbx) => {
model = fbx;
if (NORMALIZE_SCALE) {
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize(new THREE.Vector3());
const maxDim = Math.max(size.x, size.y, size.z) || 1;
const scale = 20.0 / maxDim;
model.scale.setScalar(scale);
const center = box.getCenter(new THREE.Vector3()).multiplyScalar(scale);
model.position.sub(center);
}
ps1ifyMaterials(model);
scene.add(model);
if (fbx.animations?.length) {
mixer = new THREE.AnimationMixer(model);
mixer.clipAction(fbx.animations[0]).play();
}
autoFogFor(model);
addCampfire(FIRE_POS);
},
undefined,
() => {
addCampfire(FIRE_POS);
}
);
let fireGroup = null,
fireLight = null,
fireLight2 = null,
fireSprite = null;
function makeFlameTexture(size = 128) {
const c = document.createElement("canvas");
c.width = c.height = size;
const g = c.getContext("2d");
const grd = g.createRadialGradient(
size * 0.5,
size * 0.6,
size * 0.05,
size * 0.5,
size * 0.6,
size * 0.5
);
grd.addColorStop(0.0, "rgba(255,255,255,1)");
grd.addColorStop(0.25, "rgba(255,200,80,0.95)");
grd.addColorStop(0.55, "rgba(255,120,30,0.65)");
grd.addColorStop(0.85, "rgba(200,40,10,0.25)");
grd.addColorStop(1.0, "rgba(0,0,0,0)");
g.fillStyle = grd;
g.fillRect(0, 0, size, size);
const tex = new THREE.CanvasTexture(c);
tex.generateMipmaps = false;
tex.minFilter = THREE.NearestFilter;
tex.magFilter = THREE.NearestFilter;
tex.anisotropy = 0;
return tex;
}
function addCampfire(pos) {
fireGroup = new THREE.Group();
fireGroup.position.copy(pos);
scene.add(fireGroup);
fireLight = new THREE.PointLight(
0xff7a2a,
FIRE_MAIN_INTENSITY,
FIRE_MAIN_DISTANCE,
FIRE_DECAY
);
fireLight.position.set(0, FIRE_HEIGHT_OFFSET + 0.6, 0);
fireGroup.add(fireLight);
fireLight2 = new THREE.PointLight(
0xff3300,
FIRE_SUB_INTENSITY,
FIRE_SUB_DISTANCE,
FIRE_DECAY
);
fireLight2.position.set(0.35, FIRE_HEIGHT_OFFSET + 0.4, -0.2);
fireGroup.add(fireLight2);
const flameTex = makeFlameTexture(128);
const mat = new THREE.SpriteMaterial({
map: flameTex,
color: 0xffffff,
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending,
depthTest: true,
});
fireSprite = new THREE.Sprite(mat);
fireSprite.position.set(0, FIRE_HEIGHT_OFFSET + 0.25, 0);
fireSprite.scale.set(FIRE_SPRITE_SIZE, FIRE_SPRITE_SIZE * 1.35, 1);
fireGroup.add(fireSprite);
const base1 = FIRE_MAIN_INTENSITY,
base2 = FIRE_SUB_INTENSITY;
let t = 0;
perFrame.push((dt) => {
t += dt;
const pulse = 0.45 * Math.sin(t * 5.4) + 0.28 * Math.sin(t * 8.7 + 1.1);
fireLight.intensity = base1 + pulse;
fireLight2.intensity = base2 + pulse * 0.75;
fireLight.color.setHSL(0.06 + Math.sin(t * 1.6) * 0.01, 1.0, 0.55);
fireLight2.color.setHSL(
0.03 + Math.sin(t * 1.9 + 0.8) * 0.012,
1.0,
0.47
);
fireSprite.material.rotation += dt * 0.5;
const j = 1.0 + Math.sin(t * 6.0) * 0.06;
fireSprite.scale.set(
FIRE_SPRITE_SIZE * j,
FIRE_SPRITE_SIZE * 1.35 * j,
1
);
});
}
function animate() {
if (!active) return;
const dt = clock.getDelta();
if (mixer) mixer.update(dt);
updateCameraHover(dt);
perFrame.forEach((fn) => fn(dt));
renderer.setRenderTarget(rt);
postMat.uniforms.tDiffuse.value = null;
renderer.clear();
renderer.render(scene, camera);
renderer.setRenderTarget(null);
postMat.uniforms.tDiffuse.value = rt.texture;
postMat.uniforms.uTime.value += dt;
renderer.render(postScene, postCam);
requestAnimationFrame(animate);
}
const clock = new THREE.Clock();
let active = true;
addEventListener("visibilitychange", () => {
active = document.visibilityState === "visible";
if (active) requestAnimationFrame(animate);
});
const fadeIn = () => requestAnimationFrame(() => (canvas.style.opacity = "1"));
requestAnimationFrame(() => {
animate();
requestAnimationFrame(fadeIn);
});
addEventListener("resize", () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
resizeRenderer();
updateFooterClip();
patchedMaterials.forEach((m) => {
const s = m.userData._ps1Shader;
if (s) s.uniforms.uResolution.value.set(innerWidth, innerHeight);
});
});
const audio = new Audio("https://seppjm.com/3js/audio/stalker.mp3");
audio.loop = true;
audio.preload = "auto";
audio.crossOrigin = "anonymous";
audio.volume = 0.5;
const btn = document.createElement("button");
btn.type = "button";
btn.textContent = "Play music";
btn.setAttribute("aria-pressed", "false");
btn.ariaLabel = "Toggle background music";
Object.assign(btn.style, {
position: "fixed",
right: "16px",
bottom: "16px",
zIndex: "3",
padding: "10px 14px",
borderRadius: "9999px",
border: "1px solid rgba(255,255,255,0.25)",
background: "rgba(0,0,0,0.45)",
color: "white",
font:
"500 14px/1.1 system-ui, -apple-system, Segoe UI, Roboto, Inter, sans-serif",
backdropFilter: "blur(6px)",
WebkitBackdropFilter: "blur(6px)",
cursor: "pointer",
userSelect: "none",
});
document.body.appendChild(btn);
let isPlaying = false,
fadeRAF = null;
function fadeTo(target, ms = 700) {
cancelAnimationFrame(fadeRAF);
const start = audio.volume,
delta = target - start,
t0 = performance.now();
const tick = (now) => {
const p = Math.min(1, (now - t0) / ms);
audio.volume = Math.max(0, Math.min(1, start + delta * p));
if (p < 1) fadeRAF = requestAnimationFrame(tick);
};
fadeRAF = requestAnimationFrame(tick);
}
async function playAudio() {
try {
await audio.play();
isPlaying = true;
btn.textContent = "Pause music";
btn.setAttribute("aria-pressed", "true");
fadeTo(0.5, 600);
} catch {}
}
function pauseAudio() {
fadeTo(0.0, 400);
setTimeout(() => audio.pause(), 420);
isPlaying = false;
btn.textContent = "Play music";
btn.setAttribute("aria-pressed", "false");
}
btn.addEventListener("click", () =>
isPlaying ? pauseAudio() : playAudio()
);
const startOnGesture = () => {
if (!isPlaying) playAudio();
removeEventListener("pointerdown", startOnGesture);
removeEventListener("keydown", startOnGesture);
};
addEventListener("pointerdown", startOnGesture, { once: true });
addEventListener("keydown", startOnGesture, { once: true });
})();

239
3js/index.html Normal file
View File

@@ -0,0 +1,239 @@
<!DOCTYPE html>
<!-- hey, there is no need to inspect! The source code is available for free!
https://github.com/SEPPDROID/seppjm-com
feel free to take & use it.
(ps: check out Skeleton too: http://getskeleton.com/ | https://github.com/dhg/Skeleton)
-->
<html lang="en">
<head>
<!-- Basic Page Needs
-->
<meta charset="utf-8">
<title>SEPPJM.COM</title>
<meta name="description" content="Home | SeppJM.com">
<meta name="author" content="Sepp -seppdroid- Jeremiah Morris">
<!-- Mobile Specific Metas
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- FONT
-->
<link href="//sjm.cdn.prutzel.com/fonts/crn/font.css" rel="stylesheet" type="text/css">
<!-- CSS
-->
<link rel="stylesheet" href="//sjm.cdn.prutzel.com/css/normalize.css">
<link rel="stylesheet" href="//sjm.cdn.prutzel.com/css/skeleton.css">
<link rel="stylesheet" href="//sjm.cdn.prutzel.com/fonts/font-awesome-4.7.0/css/font-awesome.min.css">
<!-- Favicon
-->
<link rel="icon" type="image/png" href="//sjm.cdn.prutzel.com/images/favicon.png">
</head>
<body>
<div class="nav">
<!-- NAV
-->
<nav id="navbar" style="top: 0px;">
<div id="navlinks">
<a href="https://seppjm.com">Home</a>
<a href="#About">AboutMe</a>
<a href="https://cv.seppjm.com">CV</a>
<a href="https://diodematrix.com">DiodeMatrix</a>
<a href="https://brain.seppdroid.com">BrainBlog</a>
<div class="dropdown">
<a href="javascript:void(0);" class="dropbtn" onclick="DropFunc()">Links
<i class="fa fa-caret-down"></i>
</a>
<div class="dropdown-content" id="DropList">
<a href="https://twitter.com/seppdroid">Twitter</a>
<a href="https://www.instagram.com/seppdroid/">Instagram</a>
<a href="https://github.com/SEPPDROID">Github</a>
<a href="contact.html">Contact</a>
</div>
</div>
</div>
<div id="burgermenu">
<a class="fa fa-bars" href="javascript:void(0);" style="font-size: 22px;" onclick="BurgMenFunc()"></a>
</div>
</nav>
</div>
<div class="container">
<!-- Primary Page Layout
-->
<div class="row">
<div class="column" style="margin-top: 17%">
<center><h3>Welcome</h3></center>
<center><p>Welcome to my webpage, Where can i take you today?</p></center>
<br>
<center>
<a class="button" href="#About">About me</a>
<a class="button" href="https://brain.seppdroid.com">my BRAiN</a>
<a class="button" href="https://cv.seppjm.com">my CV</a>
</center><br>
<center><p>---</p></center><br>
<center><p>I might add more links & content to this website soon. You can find more links under the "Links" dropdown menu.</p></center>
</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="one-half column" style="margin-top: 60%" id="About">
<br>
<h4>About me</h4>
<p>Hi i'm Sepp! While I might add more content to my website at some point, writing about more interesting topics is what truly excites me. After all, who's really interested in this page, right?</p>
<p>I made this website to save you from a <code>404</code> or <code>403</code>.</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
</div>
</div>
<footer>
<br>
<p>Sepp & Skeleton |
<a href="https://github.com/SEPPDROID/seppjm-com">Source</a>
<a href="http://getskeleton.com">Skeleton</a></p>
</footer>
<!-- JS
-->
<script src="https://sjm.cdn.prutzel.com/js/script.js"></script>
<script async src="https://unpkg.com/es-module-shims@1.10.0/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
}
}
</script>
<script type="module" src="https://seppjm.com/3js/background.js"></script>
<!-- End Document
-->
</body>
</html>

BIN
3js/models/scene.fbx Normal file

Binary file not shown.

View File

@@ -220,6 +220,18 @@
<!-- JS <!-- JS
--> -->
<script src="https://sjm.cdn.prutzel.com/js/script.js"></script> <script src="https://sjm.cdn.prutzel.com/js/script.js"></script>
<script async src="https://unpkg.com/es-module-shims@1.10.0/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
}
}
</script>
<script type="module" src="https://seppjm.com/3js/background.js"></script>
<!-- End Document <!-- End Document
--> -->

227
oldindex.html Normal file
View File

@@ -0,0 +1,227 @@
<!DOCTYPE html>
<!-- hey, there is no need to inspect! The source code is available for free!
https://github.com/SEPPDROID/seppjm-com
feel free to take & use it.
(ps: check out Skeleton too: http://getskeleton.com/ | https://github.com/dhg/Skeleton)
-->
<html lang="en">
<head>
<!-- Basic Page Needs
-->
<meta charset="utf-8">
<title>SEPPJM.COM</title>
<meta name="description" content="Home | SeppJM.com">
<meta name="author" content="Sepp -seppdroid- Jeremiah Morris">
<!-- Mobile Specific Metas
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- FONT
-->
<link href="//sjm.cdn.prutzel.com/fonts/crn/font.css" rel="stylesheet" type="text/css">
<!-- CSS
-->
<link rel="stylesheet" href="//sjm.cdn.prutzel.com/css/normalize.css">
<link rel="stylesheet" href="//sjm.cdn.prutzel.com/css/skeleton.css">
<link rel="stylesheet" href="//sjm.cdn.prutzel.com/fonts/font-awesome-4.7.0/css/font-awesome.min.css">
<!-- Favicon
-->
<link rel="icon" type="image/png" href="//sjm.cdn.prutzel.com/images/favicon.png">
</head>
<body>
<div class="nav">
<!-- NAV
-->
<nav id="navbar" style="top: 0px;">
<div id="navlinks">
<a href="https://seppjm.com">Home</a>
<a href="#About">AboutMe</a>
<a href="https://cv.seppjm.com">CV</a>
<a href="https://diodematrix.com">DiodeMatrix</a>
<a href="https://brain.seppdroid.com">BrainBlog</a>
<div class="dropdown">
<a href="javascript:void(0);" class="dropbtn" onclick="DropFunc()">Links
<i class="fa fa-caret-down"></i>
</a>
<div class="dropdown-content" id="DropList">
<a href="https://twitter.com/seppdroid">Twitter</a>
<a href="https://www.instagram.com/seppdroid/">Instagram</a>
<a href="https://github.com/SEPPDROID">Github</a>
<a href="contact.html">Contact</a>
</div>
</div>
</div>
<div id="burgermenu">
<a class="fa fa-bars" href="javascript:void(0);" style="font-size: 22px;" onclick="BurgMenFunc()"></a>
</div>
</nav>
</div>
<div class="container">
<!-- Primary Page Layout
-->
<div class="row">
<div class="column" style="margin-top: 17%">
<center><h3>Welcome</h3></center>
<center><p>Welcome to my webpage, Where can i take you today?</p></center>
<br>
<center>
<a class="button" href="#About">About me</a>
<a class="button" href="https://brain.seppdroid.com">my BRAiN</a>
<a class="button" href="https://cv.seppjm.com">my CV</a>
</center><br>
<center><p>---</p></center><br>
<center><p>I might add more links & content to this website soon. You can find more links under the "Links" dropdown menu.</p></center>
</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="one-half column" style="margin-top: 60%" id="About">
<br>
<h4>About me</h4>
<p>Hi i'm Sepp! While I might add more content to my website at some point, writing about more interesting topics is what truly excites me. After all, who's really interested in this page, right?</p>
<p>I made this website to save you from a <code>404</code> or <code>403</code>.</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
</div>
</div>
<footer>
<br>
<p>Sepp & Skeleton |
<a href="https://github.com/SEPPDROID/seppjm-com">Source</a>
<a href="http://getskeleton.com">Skeleton</a></p>
</footer>
<!-- JS
-->
<script src="https://sjm.cdn.prutzel.com/js/script.js"></script>
<!-- End Document
-->
</body>
</html>