hmn/src/templates/src/jam_2023_wrj_index.html

428 lines
24 KiB
HTML

{{ template "wheeljam_2023_base.html" . }}
{{ define "content" }}
{{ $discordInviteURL := "https://discord.gg/hmn" }}
<style>
.projects {
display: grid;
grid-template-columns: 1fr;
}
@media screen and (min-width: 30em) {
/* not small styles */
.projects {
grid-template-columns: 1fr 1fr;
}
}
</style>
<div id="top-container" class="flex flex-column items-center ph3">
<img id="logo" src="{{ static "wheeljam2023/logo.svg" }}">
<h1 id="title">Wheel Reinvention Jam</h1>
<h2 id="dates">September 25 - October 1, 2023</h2>
<div id="tagline" class="center">
A one-week jam where you start from scratch.
{{ if gt .DaysUntilEnd 0 }}
{{ if eq .DaysUntilStart 0 }}
<b>Happening now.</b>
{{ else if eq .DaysUntilStart 1 }}
<b>Starting tomorrow.</b>
{{ else }}
<b>In {{ .DaysUntilStart }} days.</b>
{{ end }}
{{ end }}
</div>
<div class="actions flex justify-center">
{{ if gt .DaysUntilStart 0 }}
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns" target="_blank" href="https://github.com/HandmadeNetwork/wishlist/discussions">Get inspired</a>
{{ else if gt .DaysUntilEnd 0 }}
{{ if .SubmittedProjectUrl }}
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns" target="_blank" href="{{ .SubmittedProjectUrl }}">Share your progress</a>
{{ else }}
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns ml3" target="_blank" href="{{ .ProjectSubmissionUrl }}">Create your project</a>
{{ end }}
{{ else }}
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns ml3" href="{{ .ShowcaseFeedUrl }}">See the results</a>
{{ end }}
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns ml3" target="_blank" href="{{ $discordInviteURL }}">Join the Discord</a>
</div>
</div>
<div class="section mw8 margin-center ph3 ph4-l mv4">
<p>
The <b>Wheel Reinvention Jam</b> is a one-week jam where we build software from scratch.
</p>
<p>
Why build things from scratch? Because that's the only way real progress is made. Every impactful project started life as a small experiment. Plus, writing something from scratch turns theory into practice. You may think you know how a piece of technology works, but until you write it yourself, it won't really stick. There's no substitute for direct experience.
</p>
<p>
And let's face it, most of the software we use is basically the same as it was twenty or thirty years ago. Our "wheels" are terrible! They need to be reinvented!
</p>
<p>
So take this opportunity to try something ambitious, something weird, an unfamiliar take on a familiar problem. Who's gonna stop you?
</p>
</div>
{{ if eq .DaysUntilEnd 0 }}
<div class="section bg-black-20 pv4 overflow-hidden">
<div class="mw8 margin-center ph3 ph4-l">
<h2>Submitted projects</h2>
<div class="mt3 projects g3 back-to-normal">
{{ range .JamProjects }}
{{ template "project_card.html" projectcarddata . "" }}
{{ end }}
</div>
<div class="actions flex justify-center">
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns ml3" href="{{ .ShowcaseFeedUrl }}">See all updates</a>
</div>
</div>
</div>
{{ else if and (eq .DaysUntilStart 0) (not (eq .ShowcaseJson "[]")) }}
<div id="showcase-outer-container" class="bg-black-20 pt4 pb3 pb4-ns">
<div class="section mw8 margin-center ph3 ph4-l">
{{ if gt .DaysUntilEnd 0 }}
<h2>Recent updates</h2>
<p>
These screenshots and videos were shared by jam participants in <b>#project-showcase</b> on our <a href="{{ $discordInviteURL }}" target="_blank">Discord</a>. Join us and share what you're working on! <a class="b" href="{{ .ShowcaseFeedUrl }}">See all ➜</a>
</p>
{{ else }}
<h2>Community showcase</h2>
<p>
These screenshots and videos were shared by jam participants in <b>#project-showcase</b> on our <a href="https://discord.gg/hmn" target="_blank">Discord</a> during the jam. Join us and chat about your favorites!
</p>
{{ end }}
<div id="showcase-container" class="mw8 center-layout mh2 mh0-ns"></div>
<div class="actions flex justify-center">
<a class="ba b--white br2 pv2 pv3-ns ph3 ph4-ns ml3" target="_blank" href="{{ .ShowcaseFeedUrl }}">See all</a>
</div>
</div>
</div>
{{ template "showcase_templates.html" }}
<!-- Copy-pasted and mangled from showcase.html -->
<script>
const ROW_HEIGHT = 300;
const ITEM_SPACING = 4;
const showcaseItems = JSON.parse("{{ .ShowcaseJson }}");
const addThumbnailFuncs = new Array(showcaseItems.length);
const showcaseOuterContainer = document.querySelector('#showcase-outer-container');
let showcaseContainer = document.querySelector('#showcase-container');
// showcaseOuterContainer.classList.toggle('dn', showcaseItems.length === 0);
const itemElements = []; // array of arrays
for (let i = 0; i < showcaseItems.length; i++) {
const item = showcaseItems[i];
const [itemEl, addThumbnail] = makeShowcaseItem(item);
itemEl.container.setAttribute('data-index', i);
itemEl.container.setAttribute('data-date', item.date);
addThumbnailFuncs[i] = addThumbnail;
itemElements.push(itemEl.container);
}
function layout() {
const width = showcaseContainer.getBoundingClientRect().width;
showcaseContainer = emptyElement(showcaseContainer);
function addRow(itemEls, rowWidth, container) {
const totalSpacing = ITEM_SPACING * (itemEls.length - 1);
const scaleFactor = (width / Math.max(rowWidth, width));
const row = document.createElement('div');
row.classList.add('flex');
row.classList.toggle('justify-between', rowWidth >= width);
row.style.marginBottom = `${ITEM_SPACING}px`;
for (const itemEl of itemEls) {
const index = parseInt(itemEl.getAttribute('data-index'), 10);
const item = showcaseItems[index];
const aspect = item.width / item.height;
const baseWidth = (aspect * ROW_HEIGHT) * scaleFactor;
const actualWidth = baseWidth - (totalSpacing / itemEls.length);
itemEl.style.width = `${actualWidth}px`;
itemEl.style.height = `${scaleFactor * ROW_HEIGHT}px`;
itemEl.style.marginRight = `${ITEM_SPACING}px`;
row.appendChild(itemEl);
}
container.appendChild(row);
}
let rowItemEls = [];
let rowWidth = 0;
let numRows = 0;
for (const itemEl of itemElements) {
const index = parseInt(itemEl.getAttribute('data-index'), 10);
const item = showcaseItems[index];
const aspect = item.width / item.height;
rowWidth += aspect * ROW_HEIGHT;
rowItemEls.push(itemEl);
if (rowWidth > width) {
addRow(rowItemEls, rowWidth, showcaseContainer);
numRows += 1;
if (numRows == 3) {
return;
}
rowItemEls = [];
rowWidth = 0;
}
}
addRow(rowItemEls, rowWidth, showcaseContainer);
}
function loadImages() {
const items = showcaseContainer.querySelectorAll('.showcase-item');
for (const item of items) {
const i = parseInt(item.getAttribute('data-index'), 10);
addThumbnailFuncs[i]();
}
}
layout();
layout(); // scrollbars are fun!!
loadImages();
window.addEventListener('resize', () => {
layout();
});
</script>
{{ else }}
<div class="section bg-black-20 pv4 overflow-hidden">
<div class="mw8 margin-center ph3 ph4-l">
<h2>Last year's entries</h2>
<p>
We had 28 incredible entries <a href="https://handmade.network/jam/2022">last year</a>. Here are a few of our favorites:
</p>
<div class="carousel-container">
<div class="carousel bg-white-10 br3 pa3 pa4-ns">
<div class="carousel-item active">
<video controls class="br2" src="https://hmn-assets-2.ams3.cdn.digitaloceanspaces.com/2c3ea96c-f246-4f03-9f2d-3538d7ffaf90/embed"></video>
<h3>SDF Atlas</h3>
<p>
SDF Atlas is an interactive editor for signed distance fields. Signed distance fields are commonly used to make beautiful implicit geometry in shaders, but editing them leaves a lot to be desired - editing shapes with shader code is not the most pleasant experience.
</p>
<p>
SDF Atlas gives you an interactive UI for playing with SDFs, including transformations like repetition and reflection that make SDFs such a popular choice for shader programmers. But it also goes a step further by creating an "atlas" format that allows for easy drawing of any shapes you create in the editor, without having to write all the shader code yourself.
</p>
<p>
This project was featured at Handmade Seattle in 2022.
</p>
<a class="b db" href="https://handmade.network/p/274/sdf-atlas/">Full Submission ➜</a>
<a class="b db" href="https://www.youtube.com/watch?v=BkOsE63bGuA&t=164s" target="_blank">Recap Interview ➜</a>
<a class="b db" href="https://guide.handmade-seattle.com/c/2022/sdf-atlas/" target="_blank">Handmade Seattle Demo ➜</a>
</div>
<div class="carousel-item">
<video controls class="br2" src="https://hmn-assets-2.ams3.cdn.digitaloceanspaces.com/71201dd3-3333-4ac5-a749-2b3c5d896a85/day3_short.mov"></video>
<h3>Orca</h3>
<p>
The Orca prototype is "a launcher for WebAssembly applications". But in reality, it's more than that. It demonstrated the ability to use WebAssembly as the foundation for cross-platform applications while swapping out the entire web stack for something new. It's a taste of a new vision for the web.
</p>
<p>
The prototype version was such a success that we decided to turn it into a <a href="https://orca-app.dev/" target="_blank">proper Handmade initiative, and the author, Martin, has been working full-time on Orca since earlier this year - in fact, it's now available to use as a platform for this year's jam.
</p>
<a class="b db" href="https://handmade.network/p/294/orca/">Full Submission ➜</a>
<a class="b db" href="https://www.youtube.com/watch?v=BkOsE63bGuA&t=4409s" target="_blank">Recap Interview ➜</a>
<a class="b db" href="https://orca-app.dev/" target="_blank">Orca Website ➜</a>
</div>
<div class="carousel-item">
<img class="br2" src="https://hmn-assets-2.ams3.cdn.digitaloceanspaces.com/b015f14e-b51a-4df9-b2d5-6c594be25373/Screenshot_from_2022-08-22_09-44-50.png">
<h3>Bifold Text</h3>
<p>
Bifold text is a wonderfully imaginative and experimental project that asks the question - what if each line of code was two lines of code?
</p>
<p>
Bifold Text is an experimental code format, editor, and execution runtime that allows you to write debug print statements interleaved with your actual program. Rather than harm your program's legibility by spamming your code with logs, the editor can tuck your debug code out of the way, ready to pull out and edit at a moment's notice. It also includes new graphical features for debug prints, so you can have more than just a text file - you can have a rich visual history of your program's execution.
</p>
<a class="b db" href="https://handmade.network/p/283/bifold-text/">Full Submission ➜</a>
<a class="b db" href="https://www.youtube.com/watch?v=BkOsE63bGuA&t=3665s" target="_blank">Recap Video ➜</a>
</div>
<div class="carousel-item">
<img class="br2" src="https://hmn-assets-2.ams3.cdn.digitaloceanspaces.com/62006e6b-eaa0-495a-a4c3-7ae077e27e46/image.png">
<h3>Netsim</h3>
<p>
Netsim is a toy network in a box, designed for education. It simulates real network and routing protocols and allows you to visualize network properties like congestion control.
</p>
<p>
The jam prototype has fairly complete implementations of TCP and IPv4 running entirely within the browser. By implementing the network stack itself, it can tune everything to make visualizations clear and easy to understand. It also makes lots of pleasant noises as traffic flows through the network.
</p>
<a class="b db" href="https://handmade.network/p/293/netsim/">Full Submission ➜</a>
</div>
<div class="carousel-thinger next"></div>
<div class="carousel-thinger prev"></div>
</div>
<div class="carousel-buttons mt2 pv2"></div>
</div>
</div>
</div>
{{ end }}
<div class="pt4 pb3 pb4-ns">
<div class="section mw8 margin-center ph3 ph4-l">
<h2>How to participate</h2>
<p>
The jam takes place from Monday, September 25 through Sunday, October 1. Here's how you can participate:
</p>
<div class="{{ if gt .DaysUntilStart 0 }}emphasized{{ end }}">
<h3>Pick a project and form a team.</h3>
<p>
Find a project idea that excites you! Join the conversation over on our <a href="https://github.com/HandmadeNetwork/wishlist/discussions" target="_blank">Wishlist</a>, brainstorm ideas on <a href="{{ $discordInviteURL }}" target="_blank">Discord</a>, or just invite some friends to jam with you.
</p>
</div>
<div class="{{ if and (eq .DaysUntilStart 0) (gt .DaysUntilEnd 1) }}emphasized{{ end }}">
<h3>Jam.</h3>
<p>
{{ if and (eq .DaysUntilStart 0) (not .SubmittedProjectUrl) }}
<a href="{{ .ProjectSubmissionUrl }}" target="_blank"><b>Create a Handmade Network project</b></a>
{{ else }}
After the jam starts, create a Handmade Network project
{{ end }}
to track your work. Then, build your program! Share your work in progress in #project-showcase on Discord, or directly from your project page. Posts on Discord can be tagged so they automatically appear here on the website.
</p>
</div>
<div class="{{ if eq .DaysUntilEnd 1 }}emphasized{{ end }}">
<h3>Submit your work!</h3>
<p>
<b>Your Handmade Network project is your submission.</b> Fill out the project description, making sure to explain the goals of the project and why you chose to build it. Also consider posting an update with video of your program in action!
</p>
{{ if and (eq .DaysUntilStart 0) (gt .DaysUntilEnd 0) }}
<p>
Submissions close <b><span class="countdown" data-deadline="{{ .EndTimeUnix }}"></span></b>.
</p>
{{ else if eq .DaysUntilEnd 0 }}
<p>
<b>Submissions are now closed.</b>
</p>
{{ end }}
</div>
</div>
</div>
<div class="bg-black-20 pt4 pb3 pb4-ns">
<div class="section mw8 margin-center ph3 ph4-l">
<h2>Rules</h2>
<ul>
<li>Any tech is allowed. Popular tech choices in the community are <a href="https://www.raylib.com/">Raylib</a>, <a href="https://www.libsdl.org/">SDL</a>, <a href="https://github.com/ocornut/imgui">Dear ImGui</a>, and <a href="https://github.com/rxi/microui">microui</a>. Or if you're feeling ambitious, you can even use our new app platform, Orca!</li>
<li>You may work solo or in a team.</li>
<li>Submit your work by the end of the day on October 1.</li>
</ul>
<p>There are no explicit winners, but we will be selecting a few of our favorite projects to highlight in a recap stream following the jam.</p>
<h3>Submission rules</h3>
<p>
<b>{{ with .SubmittedProjectUrl }}
<a href="{{ . }}" target="_blank">Your Handmade Network project</a>
{{ else }}
Your Handmade Network project
{{ end }}
is your submission.</b> We will be looking at the project's description and any extra updates you share toward the end of the jam.
</p>
<ul>
<li>
Explain the project's goals and why you chose to build it. Also share some closing thoughts - did it turn out how you hoped? What did you learn? If you continue the project, what will you do differently?
</li>
<li>
<b>Your description must contain multiple screenshots of your software in action.</b> You should ideally also share a project update with a demo video. We recommend Mārtiņš Možeiko's <a href="https://wcap.handmade.network/" target="_blank">wcap</a> for recording desktop video on Windows. On Mac, just press ⌘-Option-5 and record a video, or use QuickTime.
</li>
<li>If possible, please provide a way for people to either build or download your program.</li>
</ul>
</div>
</div>
<div class="pt4">
<div class="flex-ns flex-row-ns mw8 margin-center ph3 ph4-l">
<div class="section flex-fair mb4 mb0-ns">
<h2>Make it by hand.</h2>
<p>
The Handmade ethos and Handmade community are software development superpowers. Don't be afraid to question your foundations and rebuild what needs rebuilding. The community is here to help you take on those challenges and do what others might consider impossible.
</p>
<p>
Of course, this is a jam, so focus on what matters to your project. There are many excellent libraries in the community that can save you time and help you focus on your core ideas. Don't be afraid to use them. But don't be afraid to do your own thing if they're holding you back.
</p>
</div>
<div class="section flex-fair ml4-m ml5-l">
<h2>Don't just rebuild. Reinvent.</h2>
<p>
This is a chance to build something new, weird, and different. Don't settle for “the same, but better” - it would be a shame to build a mere clone of the same old software we use today.
</p>
<p>
Of course, if you want to build a clone just for educational value, that's great! But while you're doing it, why not put your own spin on it? This is the perfect time to experiment with even the tiniest ideas. And if you're out of ideas, consider working with a team - collaborating with someone is the perfect way to generate new ideas and tackle bigger projects than you could handle on your own.
</p>
<p>
This is a jam. Don't be afraid to try something weird!
</p>
</div>
</div>
</div>
<script>
const carouselContainer = document.querySelector('.carousel-container');
if (carouselContainer) {
const { next, prev } = initCarousel(carouselContainer, {
onChange() {
if (carouselContainer.getBoundingClientRect().top < 0) {
carouselContainer.scrollIntoView({ behavior: 'smooth' });
}
},
});
document.querySelector('.carousel-thinger.next')
.addEventListener('click', () => {
next();
});
document.querySelector('.carousel-thinger.prev')
.addEventListener('click', () => {
prev();
});
}
</script>
<script>
for (const countdown of document.querySelectorAll('.countdown')) {
const deadline = countdown.getAttribute('data-deadline');
const deadlineDate = new Date(parseInt(deadline, 10) * 1000);
function updateCountdown() {
const remainingMs = deadlineDate.getTime() - new Date().getTime();
const remainingMinutes = remainingMs / 1000 / 60;
const remainingHours = remainingMinutes / 60;
const remainingDays = remainingHours / 24; // no daylight savings transitions during the jam mmkay
let str = 'imminently';
if (remainingMinutes < 60) {
str = `in ${Math.ceil(remainingMinutes)} ${remainingMinutes === 1 ? 'minute' : 'minutes'}`;
} else if (remainingHours < 24) {
str = `in ${Math.ceil(remainingHours)} ${remainingHours === 1 ? 'hour' : 'hours'}`;
} else {
str = `in ${Math.ceil(remainingDays)} ${remainingDays === 1 ? 'day' : 'days'}`;
}
countdown.innerText = str;
}
updateCountdown();
setInterval(updateCountdown, 1000 * 60);
}
</script>
{{ end }}