<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>About u :D</title>
<link rel="stylesheet" href="lib/style.css" />
<script>
// remove me
document.addEventListener('DOMContentLoaded', () => {
// alert('https://github.com/deeegen/public-profile-template');
});
</script>
</head>
<body>
<header class="header" style="position: relative;">
<h1>Welcome!</h1>
<canvas id="oscilloscope" style="
position: absolute;
top: 60px;
left: 0;
width: 100%;
height: 100px;
z-index: 0;
background-color: transparent;
"></canvas>
<audio id="audio" controls crossorigin="anonymous" style="position: relative; z-index: 1;"></audio>
<ul id="playlist"></ul>
</header>
<section class="grid">
<div class="iframe-overlay" id="iframeOverlay">
<div class="close-btn" id="closeOverlay">×</div>
<iframe id="iframeContent" src=""></iframe>
</div>
<div class="side-container">
<div class="profile">
<div class="profile-picture-container">
<img
src="https://tr.rbxcdn.com/180DAY-3f9aceb0bb3efd1c0283638edb3f84bf/420/420/Hat/Webp/noFilter"
alt="Profile picture"
class="profile-img"
/>
</div>
<h2>@username</h2>
<div class="status">Status</div>
<p>Share a short bio or tagline here.</p>
<div class="social-links">
<a href="#" target="_blank" class="social-btn" title="Twitter">
<img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="Twitter" />
</a>
<a href="#" target="_blank" class="social-btn" title="GitHub">
<img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="GitHub" />
</a>
<a href="#" target="_blank" class="social-btn" title="LinkedIn">
<img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="LinkedIn" />
</a>
</div>
</div>
<div class="media">
<img src="https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png" alt="Media Image" />
<p><strong>Interests:</strong></p>
<p>- Interest one</p>
<p>- Interest two</p>
<p>- Interest three</p>
</div>
<button id="openBlog" class="blog-btn">Open Blog</button>
</div>
<div class="main">
<div class="main-text">
<div class="title">Main Title</div>
<div class="subtitle">Subtitle goes here</div>
</div>
<div class="main-content-section">
<h3>Section Title</h3>
<p>Write your content here.</p>
</div>
<div class="main-content-section">
<h3>Another Section</h3>
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
</div>
</div>
</section>
<script type="application/json" id="playlist-data">
[
{"title": "Song One", "url": "https://files.catbox.moe/a61oxd.mp3"},
{"title": "Song Two", "url": "https://files.catbox.moe/7yydn8.mp3"},
{"title": "Song Three", "url": "songs/song3.mp3"}
]
</script>
<script src="lib/player.js"></script>
<script src="lib/overlays.js"></script>
</body>
</html>
/* ============================
1. BASIC SETUP FOR ALL ELEMENTS
============================ */
/* This part makes sure everything starts with no extra space around or inside elements,
and that sizes are easier to manage. You usually don't need to change this. */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* Prevent scroll on blog */
.no-scroll {
overflow: hidden;
height: 100vh;
}
/* This sets the basic look of your page: the font style, background color, and text color.
Change colors here by updating the variables in section 2 below. */
body {
font-family: Arial, sans-serif;
line-height: 1.6;
background-color: var(--color-background);
color: var(--color-text);
}
/* Links (clickable text) will have no underline and inherit text color.
You can change how links look by changing these styles. */
a {
text-decoration: none;
color: inherit;
}
/* ============================
2. COLORS, SIZES & SPACES YOU CAN CHANGE EASILY
============================ */
/* Here are all the main colors, sizes, and spacing used on the page.
To change colors or sizes, just replace the values here.
For example, to change background color, update --color-background below. */
:root {
--color-background: #fafafa; /* Page background color */
--color-surface: #ffffff; /* Background for boxes/cards */
--color-border: #e0e0e0; /* Border color around boxes */
--color-text: #333333; /* Main text color */
--color-muted: #666666; /* Secondary text color */
--color-muted-bg: #f5f5f5; /* Background for muted areas */
--color-hover-bg: #eaeaea; /* Background when you hover on items */
--color-focus: #005fcc; /* Outline color when an item is focused */
--border-radius: 8px; /* How rounded corners are */
--box-shadow-light: 0 2px 4px rgba(0, 0, 0, 0.05); /* Light shadow for depth */
--box-shadow-hover: 0 4px 8px rgba(0, 0, 0, 0.1); /* Shadow on hover */
--spacing-xs: 4px; /* Extra small space */
--spacing-s: 6px; /* Small space */
--spacing-m: 10px; /* Medium space */
--spacing-l: 20px; /* Large space */
--font-size-base: 1rem; /* Base font size */
--font-size-small: 0.95rem; /* Small font size */
--font-size-large: 1.1rem; /* Large font size */
--font-size-xl: 1.5rem; /* Extra large font size */
--font-size-xxl: 2rem; /* Double extra large font size */
}
/* ============================
3. BOX STYLES (CARDS & SECTIONS)
============================ */
/* Boxes with white background, border, rounded corners, and subtle shadow.
You can change how these boxes look by editing colors or border-radius in section 2. */
.surface {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow-light);
}
/* These sections use the same box style.
To change their look, change the variables in section 2 above. */
header,
.side-container,
.main,
.media,
.main-content-section {
background-color: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow-light);
}
/* ============================
4. PAGE LAYOUT
============================ */
/* This sets up the main layout with two columns: a side area and a main area.
Change the spacing or max width here if you want the page wider or narrower. */
.grid {
display: grid;
grid-template-areas: "side main";
grid-template-columns: 1fr 2fr;
gap: var(--spacing-l);
padding: var(--spacing-l);
max-width: 1200px;
margin: 0 auto; /* Centers the page */
}
/* Side container styles: stacked vertically with spacing */
.side-container {
grid-area: side;
padding: var(--spacing-l);
display: flex;
flex-direction: column;
gap: var(--spacing-l);
}
/* Main container styles: stacked vertically with spacing */
.main {
grid-area: main;
padding: var(--spacing-l);
display: flex;
flex-direction: column;
gap: var(--spacing-l);
}
/* ============================
5. HEADER (TOP OF THE PAGE)
============================ */
/* Header is centered with padding and space below */
.header {
text-align: center;
padding: 1.5rem var(--spacing-l);
margin-bottom: var(--spacing-l);
}
/* Main title font size and spacing */
.header h1 {
font-size: var(--font-size-xxl);
margin-bottom: var(--spacing-s);
}
/* Audio player style: size and rounded corners */
.header audio {
width: 100%;
max-width: 360px;
height: 50px;
margin: 0 auto;
display: block;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.3);
background: rgba(255, 255, 255, 0.5);
opacity: 0.9;
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
background-clip: padding-box;
outline: none;
}
.header audio:focus {
border-color: rgba(255, 255, 255, 0.6);
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.3);
}
/* Playlist container: items arranged in rows and wrap to next line */
#playlist {
list-style: none; /* Remove bullet points */
display: flex;
flex-wrap: wrap;
gap: var(--spacing-m);
justify-content: center;
margin-top: var(--spacing-s);
}
/* Individual playlist item style */
#playlist li {
background-color: var(--color-muted-bg);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: var(--spacing-s) var(--spacing-l);
cursor: pointer; /* Shows it can be clicked */
font-size: var(--font-size-small);
color: var(--color-text);
user-select: none; /* Prevents text highlight on click */
transition: background-color 0.2s, box-shadow 0.2s; /* Smooth hover effect */
white-space: nowrap; /* Keep text on one line */
/* To make these items keyboard-focusable, your HTML should include tabindex="0" */
}
/* Changes appearance when hovering or focusing (keyboard) on playlist items */
#playlist li:hover,
#playlist li:focus {
background-color: var(--color-hover-bg);
box-shadow: var(--box-shadow-hover);
outline: none;
}
/* Fix buttons kind of */
#playlist li.selected {
background-color: transparent;
border-color: #bbb;
font-weight: 600;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.playlist-button {
display: block;
width: 100%;
text-align: left;
padding: 12px 16px;
font-size: 1rem;
background: none;
border: none;
cursor: pointer;
border-radius: 6px;
transition: background 0.2s;
}
.playlist-button:hover,
.playlist-button:focus {
background-color: #e0e0e0;
outline: none;
}
li.selected .playlist-button {
background-color: transparent;
font-weight: bold;
}
/* ============================
6. PROFILE (SIDE BAR)
============================ */
/* Center text inside profile area with padding */
.profile {
text-align: center;
padding: var(--spacing-l);
}
/* Container for profile picture with margin below */
.profile-picture-container {
display: inline-block;
position: relative;
margin-bottom: var(--spacing-s);
}
/* Profile picture shape and size */
.profile-picture-container .profile-img {
width: 7.5rem; /* About 120px */
height: 7.5rem;
border-radius: 50%; /* Make it round */
border: 2px solid var(--color-border);
}
/* Profile name font size and spacing */
.profile h2 {
font-size: var(--font-size-xl);
margin-bottom: var(--spacing-s);
}
/* Status label style */
.status {
display: inline-block;
padding: var(--spacing-xs) var(--spacing-m);
border-radius: 12px;
font-size: var(--font-size-small);
border: 1px solid var(--color-border);
background-color: var(--color-muted-bg);
}
/* Profile description paragraph */
.profile p {
margin-top: var(--spacing-s);
font-size: var(--font-size-small);
}
/* ============================
7. SOCIAL LINKS (SIDE BAR)
============================ */
/* Social icons arranged in a row with spacing */
.social-links {
display: flex;
justify-content: center;
gap: var(--spacing-m);
margin-top: var(--spacing-s);
}
/* Button style for social icons: round, centered content */
.social-btn {
width: 40px;
height: 40px;
border: 1px solid var(--color-border);
border-radius: 50%;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.2s, box-shadow 0.2s;
/* In your HTML, use <a> or <button> for best accessibility */
}
/* Hover and keyboard focus effects for social buttons */
.social-btn:hover,
.social-btn:focus {
transform: translateY(-2px);
box-shadow: var(--box-shadow-hover);
outline: none;
}
/* Image inside social button fills entire button */
.social-btn img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Special button style for blog link */
.blog-btn {
display: block;
margin: 10px auto;
width: 80%;
padding: 12px 20px;
font-size: 16px;
color: #333;
background-color: #f0f0f0;
border: 2px solid #ccc;
border-radius: 6px;
filter: grayscale(100%);
transition: all 0.3s ease;
cursor: pointer;
}
/* Hover effect for blog button */
.blog-btn:hover {
background-color: #e0e0e0;
filter: grayscale(60%);
}
/* ============================
8. MEDIA SECTION (SIDE BAR)
============================ */
/* Media section padding and vertical layout */
.media {
padding: var(--spacing-l);
display: flex;
flex-direction: column;
gap: var(--spacing-s);
overflow-y: auto; /* Scroll if too tall */
}
/* Images inside media section have max width and border */
.media img {
width: 100%;
max-width: 200px;
border: 1px solid var(--color-border);
border-radius: 4px;
}
/* Text inside media section */
.media p {
font-size: var(--font-size-small);
}
/* ============================
9. MAIN CONTENT SECTIONS
============================ */
/* Main text container: centered with space below */
.main-text {
text-align: center;
margin-bottom: var(--spacing-l);
}
/* Title style */
.main-text .title {
font-size: 1.8rem;
margin-bottom: var(--spacing-s);
}
/* Subtitle style */
.main-text .subtitle {
font-size: var(--font-size-large);
color: var(--color-muted);
}
/* Main content section padding */
.main-content-section {
padding: var(--spacing-l);
}
/* Headings inside main content */
.main-content-section h3 {
font-size: 1.3rem;
margin-bottom: var(--spacing-s);
border-bottom: 1px solid var(--color-border);
padding-bottom: var(--spacing-xs);
}
/* Paragraphs and list items spacing and size */
.main-content-section p,
.main-content-section li {
margin-bottom: var(--spacing-s);
font-size: var(--font-size-small);
}
/* Lists with bullet points and indent */
.main-content-section ul {
list-style: disc;
margin-left: var(--spacing-l);
}
/* ============================
10. POP-UP OVERLAY (IFRAME MODAL)
============================ */
/* Hidden by default. This is the dark transparent background behind the pop-up box */
.iframe-overlay {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
}
/* When active, show the overlay and center its content */
.iframe-overlay.active {
display: flex;
}
/* The pop-up box with no border and rounded corners */
.iframe-overlay iframe {
width: 90%;
height: 90%;
border: none;
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* Close button for the pop-up, positioned top right */
.iframe-overlay .close-btn {
position: absolute;
top: var(--spacing-l);
right: var(--spacing-l);
font-size: 1.5rem;
cursor: pointer;
background: transparent;
border: none;
}
/* ============================
11. HOW TO SEE FOCUSED ELEMENTS (KEYBOARD NAVIGATION)
============================ */
/* When you tab through links, buttons, or playlist items, a blue outline appears to show focus */
a:focus,
button:focus,
#playlist li:focus,
.social-btn:focus {
outline: 2px solid var(--color-focus);
outline-offset: 2px;
}
[
{
"title": "Blog 1",
"date": "June 5, 2025",
"content": "Text text text [img]https://firstbenefits.org/wp-content/uploads/2017/10/placeholder.png[/img]."
},
{
"title": "Blog 2",
"date": "June 2, 2025",
"content": "Text text text."
},
{
"title": "Blog 3",
"date": "May 25, 2025",
"content": "Text text text."
}
]
/* ============================
RESOURCES FOR LEARNING CSS
============================ */
/*
Here are some high-quality, newb-friendly resources to learn more about CSS:
1. **MDN Web Docs - CSS**
- Comprehensive documentation and tutorials on CSS.
- https://developer.mozilla.org/en-US/docs/Web/CSS
2. **CSS-Tricks**
- A website dedicated to providing in-depth articles and guides on CSS.
- https://css-tricks.com/
3. **W3Schools**
- Offers easy-to-follow tutorials and examples for beginners.
- https://www.w3schools.com/css/
4. **FreeCodeCamp**
- Provides interactive tutorials and projects to learn CSS.
- https://www.freecodecamp.org/learn/css/
5. **Flexbox Froggy**
- A fun game to learn CSS Flexbox layout.
- https://flexboxfroggy.com/
6. **Grid Garden**
- A game for learning CSS Grid layout.
- https://cssgridgarden.com/
7. **Codecademy**
- Offers interactive courses on CSS and responsive design.
- https://www.codecademy.com/learn/learn-css
8. **CSS Zen Garden**
- A showcase of what can be accomplished visually through CSS-based design.
- http://www.csszengarden.com/
9. **Smashing Magazine**
- Features articles, tutorials, and resources on modern CSS techniques.
- https://www.smashingmagazine.com/category/css
10. **A Complete Guide to Flexbox**
- A detailed guide on CSS Flexbox by CSS-Tricks.
- https://css-tricks.com/snippets/css/a-guide-to-flexbox/
11. **A Complete Guide to Grid**
- A comprehensive guide on CSS Grid by CSS-Tricks.
- https://css-tricks.com/snippets/css/complete-guide-grid/
12. **Learn CSS Layout**
- A step-by-step guide to CSS layout techniques.
- http://learnlayout.com/
13. **CSS Reference**
- A visual guide to CSS by Codrops.
- https://tympanus.net/codrops/css_reference/
14. **The Odin Project**
- Offers a full-stack curriculum that includes CSS.
- https://www.theodinproject.com/paths/foundations/courses/foundations#css-foundations
15. **Khan Academy**
- Provides free courses on web development, including CSS.
- https://www.khanacademy.org/computing/computer-programming/html-css
These resources will help you deepen your understanding of CSS and improve your web development skills. Happy coding!
*/
/* ============================
END OF FILE
============================ */
document.addEventListener("DOMContentLoaded", () => {
const audio = document.getElementById("audio");
const canvas = document.getElementById("oscilloscope");
const playlistDataEl = document.getElementById("playlist-data");
const playlistEl = document.getElementById("playlist");
if (!audio || !canvas || !playlistDataEl || !playlistEl) {
console.error("Required DOM elements missing.");
return;
}
// Parse playlist JSON from DOM
let playlist;
try {
playlist = JSON.parse(playlistDataEl.textContent);
} catch (e) {
console.error("Failed to parse playlist JSON:", e);
return;
}
// === Optimized Oscilloscope Class ===
class Oscilloscope {
constructor(audioElement, canvasElement, options = {}) {
this.audio = audioElement;
this.canvas = canvasElement;
this.ctx = canvasElement.getContext("2d");
this.audioContext = null;
this.analyser = null;
this.source = null;
this.animationId = null;
this.dataArray = null;
this.bufferLength = 0;
// Configuration: adjustable FFT size and FPS cap
this.fftSize = options.fftSize || 1024;
this.fps = options.fps || 30; // throttle to 30 FPS
this.lastRenderTime = 0;
this._resizeHandler = () => this._resizeCanvas();
this._init();
}
_init() {
const AudioCtx = window.AudioContext || window.webkitAudioContext;
if (!AudioCtx) {
console.warn("Web Audio API not supported.");
return;
}
this.audioContext = new AudioCtx();
this.analyser = this.audioContext.createAnalyser();
this.analyser.fftSize = this.fftSize;
this.bufferLength = this.analyser.fftSize;
this.dataArray = new Uint8Array(this.bufferLength);
this.source = this.audioContext.createMediaElementSource(this.audio);
this.source.connect(this.analyser);
this.analyser.connect(this.audioContext.destination);
this._resizeCanvas();
window.addEventListener("resize", this._resizeHandler);
if (this.audioContext.state === "suspended") {
const resume = () => {
this.audioContext.resume();
this.start();
window.removeEventListener("click", resume);
window.removeEventListener("keydown", resume);
};
window.addEventListener("click", resume);
window.addEventListener("keydown", resume);
} else {
this.start();
}
}
_resizeCanvas() {
const dpr = window.devicePixelRatio || 1;
this.canvas.width = this.canvas.clientWidth * dpr;
this.canvas.height = this.canvas.clientHeight * dpr;
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform before scaling
this.ctx.scale(dpr, dpr);
}
start() {
if (this.animationId) return;
const draw = (timestamp) => {
this.animationId = requestAnimationFrame(draw);
// Throttle FPS
if (timestamp - this.lastRenderTime < 1000 / this.fps) return;
this.lastRenderTime = timestamp;
// Optionally skip rendering if audio is paused
if (this.audio.paused) {
this.ctx.clearRect(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
return;
}
this.analyser.getByteTimeDomainData(this.dataArray);
const width = this.canvas.clientWidth;
const height = this.canvas.clientHeight;
const ctx = this.ctx;
ctx.clearRect(0, 0, width, height);
ctx.lineWidth = 2;
ctx.strokeStyle = "#595959";
ctx.beginPath();
const sliceWidth = width / this.bufferLength;
let x = 0;
for (let i = 0; i < this.bufferLength; i++) {
const v = this.dataArray[i] / 128.0;
const y = (v * height) / 2;
if (i === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
x += sliceWidth;
}
ctx.lineTo(width, height / 2);
ctx.stroke();
};
this.animationId = requestAnimationFrame(draw);
}
stop() {
if (this.animationId) {
cancelAnimationFrame(this.animationId);
this.animationId = null;
}
}
destroy() {
this.stop();
if (this.source) this.source.disconnect();
if (this.analyser) this.analyser.disconnect();
if (this.audioContext) this.audioContext.close();
window.removeEventListener("resize", this._resizeHandler);
}
}
// === Audio Playlist Logic ===
(() => {
let currentTrackIndex = null;
function getRandomTrackIndex(excludeIndex) {
if (!playlist || playlist.length === 0) return -1;
let index;
do {
index = Math.floor(Math.random() * playlist.length);
} while (index === excludeIndex && playlist.length > 1);
return index;
}
function loadTrack(index) {
if (!playlist[index]) return;
currentTrackIndex = index;
audio.src = playlist[index].url;
audio.play().catch((err) => console.warn("Audio playback failed", err));
updateSelection(index);
}
function updateSelection(selectedIndex) {
Array.from(playlistEl.children).forEach((li, idx) => {
li.classList.toggle("selected", idx === selectedIndex);
});
}
playlist.forEach((song, idx) => {
const li = document.createElement("li");
const button = document.createElement("button");
button.textContent = song.title;
button.className = "playlist-button";
button.addEventListener("click", () => loadTrack(idx));
li.appendChild(button);
playlistEl.appendChild(li);
});
const firstIndex = getRandomTrackIndex(null);
if (firstIndex !== -1) loadTrack(firstIndex);
audio.addEventListener("ended", () => {
const nextIndex = getRandomTrackIndex(currentTrackIndex);
if (nextIndex !== -1) loadTrack(nextIndex);
});
})();
new Oscilloscope(audio, canvas, { fftSize: 1024, fps: 30 });
});
(() => {
const overlay = document.getElementById("iframeOverlay");
const iframe = document.getElementById("iframeContent");
const openBlogBtn = document.getElementById("openBlog");
const closeOverlayBtn = document.getElementById("closeOverlay");
const disableBodyScroll = () => {
document.body.classList.add("no-scroll");
// Prevent scroll via keyboard
window.addEventListener("keydown", preventScrollKeys, true);
// Prevent wheel-based scrolling
window.addEventListener("wheel", preventDefault, { passive: false });
window.addEventListener("touchmove", preventDefault, { passive: false });
};
const enableBodyScroll = () => {
document.body.classList.remove("no-scroll");
window.removeEventListener("keydown", preventScrollKeys, true);
window.removeEventListener("wheel", preventDefault);
window.removeEventListener("touchmove", preventDefault);
};
const preventDefault = (e) => e.preventDefault();
const preventScrollKeys = (e) => {
const keys = [
"ArrowUp", "ArrowDown",
"PageUp", "PageDown",
"Space", " ",
"Home", "End"
];
if (keys.includes(e.key)) {
e.preventDefault();
}
};
const scrollToTop = () => {
return new Promise((resolve) => {
// Scroll smoothly to top
window.scrollTo({ top: 0, behavior: "smooth" });
// Wait until scroll completes
let lastPosition = -1;
const check = () => {
const current = window.scrollY || document.documentElement.scrollTop;
if (current === 0 || current === lastPosition) {
resolve();
} else {
lastPosition = current;
requestAnimationFrame(check);
}
};
check();
});
};
if (overlay && iframe && openBlogBtn && closeOverlayBtn) {
openBlogBtn.addEventListener("click", async () => {
await scrollToTop();
iframe.src = "views/blog.html";
overlay.classList.add("active");
disableBodyScroll();
});
closeOverlayBtn.addEventListener("click", () => {
overlay.classList.remove("active");
iframe.src = "";
enableBodyScroll();
});
}
document.querySelectorAll(".social-btn").forEach((btn) => {
btn.addEventListener("click", () => {
if (btn !== openBlogBtn) {
alert("Opening " + btn.title);
}
});
});
})();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
body {
font-family: sans-serif;
background: #f4f4f4;
color: #333;
padding: 20px;
}
.container {
max-width: 700px;
margin: auto;
background: white;
padding: 20px;
border-radius: 6px;
}
h1 {
font-size: 24px;
border-bottom: 2px solid #333;
padding-bottom: 10px;
}
.post {
margin-bottom: 30px;
}
.post h2 {
font-size: 20px;
color: #0073e6;
}
.date {
font-size: 14px;
color: #777;
}
.post img {
width: 40%;
height: auto;
display: block;
margin: 10px 0;
border-radius: 4px;
object-fit: contain;
}
@media (max-width: 600px) {
body {
padding: 10px;
}
.container {
padding: 15px;
}
h1 {
font-size: 20px;
}
.post h2 {
font-size: 18px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>Ur blog :3</h1>
<div id="posts"></div>
</div>
<script>
/**
* Replaces [img]...[/img] blocks with <img> tags safely.
* Supports multiple image tags in the content.
* @param {string} content - Blog post content string
* @returns {string} - Processed HTML string
*/
function parseContent(content) {
// Simple image tag parser - assumes well-formed input
return content.replace(/\[img\](.*?)\[\/img\]/gi, (match, url) => {
// Optionally, validate or sanitize the URL here
const safeUrl = url.trim();
return `<img src="${safeUrl}" alt="blog image" style="max-width: 100%; margin: 10px 0;" />`;
});
}
fetch('../lib/blogs.json')
.then(response => response.json())
.then(data => {
const postsContainer = document.getElementById('posts');
data.forEach(post => {
const postElement = document.createElement('div');
postElement.className = 'post';
const parsedContent = parseContent(post.content);
postElement.innerHTML = `
<h2>${post.title}</h2>
<div class="date">${post.date}</div>
<div>${parsedContent}</div>
`;
postsContainer.appendChild(postElement);
});
})
.catch(error => {
console.error('Error loading blog posts:', error);
});
</script>
</body>
</html>
Lag reduction (Oscilloscope)
Blog [img] tags
Scroll lock on blog
Fixed audio player
added oscilloscope
Added additional styling to the blog button
Explanatory comments in javascript
Added more in-depth notes to the css, along with references for newbs
https://github.com/deeegen/public-profile-template/blob/main/TUT.md
(WIP) in depth tutorial on this website templates components--
also -
https://ezgif.com/optimize recommended if you're gonna use gifs and the oscilloscope