summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--css/style.css183
-rw-r--r--img/selfie.pngbin0 -> 1413 bytes
-rw-r--r--index.html70
3 files changed, 190 insertions, 63 deletions
diff --git a/css/style.css b/css/style.css
index 92f6de0..1bb8de0 100644
--- a/css/style.css
+++ b/css/style.css
@@ -24,11 +24,20 @@
font-display: swap;
}
+@font-face {
+ font-family: 'Ronzino';
+ src: url('/font/Ronzino-Bold.woff2') format('woff2');
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
/* Theme */
:root {
--primary-color: #0000f5;
--background: #fff;
- --foreground: #191919;
+ --foreground: #000019;
+ --foreground-emphasis: #191919;
--selection-color: #ccc;
--font-libre-caslon: 'Libre Caslon', 'Times New Roman', 'Georgia', serif;
--font-ronzino: 'Ronzino', 'Arial', 'Helvetica', sans-serif;
@@ -41,6 +50,7 @@
::selection {
background-color: var(--selection-color);
+ -webkit-text-stroke: 0;
color: var(--primary-color);
}
@@ -48,7 +58,54 @@
* {margin: 0; padding: 0; box-sizing: border-box}
html { scroll-behavior: smooth }
-/* Body and base elements */
+/* Base Elements */
+h1,h2,h3,h4 { font-weight: 300 }
+li,p {
+ hyphens: auto;
+ text-align: justify;
+ transform: translateY(5px);
+}
+strong {
+ color: var(--foreground-emphasis);
+ font-weight: 700;
+}
+p { margin-bottom: var(--base-grid); }
+a[role="button"],
+button {
+ border: var(--border-width) solid var(--foreground);
+ border-radius: var(--radius);
+ background-color: var(--background);
+ color: var(--foreground);
+ cursor: pointer;
+ font-family: var(--font-ronzino);
+ font-size: 1rem;
+ line-height: 1.25;
+ font-weight: 700;
+ display: inline-block;
+ text-decoration: none;
+ transition: 0.1s all linear;
+ padding: calc(0.5lh - var(--border-width)) 1lh;
+ margin-bottom: 1lh;
+
+ &:active {
+ background-color: var(--foreground);
+ color: var(--background);
+ }
+
+ label {
+ line-height: 1.25;
+ cursor: pointer;
+ }
+}
+
+.textured {
+ h2, p, ul {
+ -webkit-text-stroke: calc(4 * var(--border-width)) var(--background);
+ paint-order: stroke fill;
+ }
+}
+
+/* The Contents */
body {
font-family: var(--font-ronzino);
color: var(--foreground);
@@ -59,6 +116,7 @@ body {
flex-direction: column;
align-items: stretch;
height: 100vh;
+
/* Header */
@@ -139,8 +197,6 @@ body {
}
}
}
-h1,h2,h3,h4 { font-weight: 300 }
-li,p { text-align: justify; }
/* The Main Body */
main {
@@ -158,9 +214,41 @@ main {
font-weight: 500;
transform: translateY(-8px);
}
+
+ ul {
+ list-style: none;
+ margin-left: 0;
+ }
+ li {
+ position: relative;
+ padding-left: var(--base-grid);
+
+ &::before {
+ content: "✷";
+ width: var(--base-grid);
+ display: inline-block;
+ margin-left: calc(-1 * var(--base-grid));
+ text-align: left;
+ }
+ }
+}
+
+#introduction {
+
+ padding: calc(1 * var(--base-grid));
+
+ .content {
+ column-gap: var(--base-grid);
+ width: 100%;
+ max-width: calc(35 * var(--base-grid));
+ background: var(--background);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
}
-.services {
+#services {
column-gap: calc(2 * var(--base-grid));
row-gap: calc(3 * var(--base-grid));
padding: calc(2 * var(--base-grid));
@@ -181,29 +269,52 @@ main {
}
}
- ul {
- list-style: none;
- margin-left: 0;
+}
+
+#skills {
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="4" height="4"><rect x="0" y="0" width="1" height="1" fill="black"/><rect x="2" y="2" width="1" height="1" fill="black"/></svg>');
+ padding: calc(2 * var(--base-grid));
+ width: 100%;
+ display: flex;
+ column-gap: calc(4 * var(--base-grid));
+ row-gap: calc(3 * var(--base-grid));
+ flex-wrap: wrap;
+
+ @media (max-width: 360px) {
+ padding: calc(2 * var(--base-grid)) var(--base-grid);
}
- li {
- position: relative;
- transform: translateY(5px);
- padding-left: var(--base-grid);
-
- &::before {
- content: "✷";
- width: var(--base-grid);
- display: inline-block;
- margin-left: calc(-1 * var(--base-grid));
- text-align: left;
+
+ section {
+ flex: 1;
+ min-width: calc(17 * var(--base-grid));
+
+ @media (max-width: 360px) {
+ min-width: calc(100vw - 3 * var(--base-grid));
}
}
}
-.skills {
- background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="4" height="4"><rect x="0" y="0" width="1" height="1" fill="black"/><rect x="2" y="2" width="1" height="1" fill="black"/></svg>');
- padding: var(--base-grid);
- width: 100vw;
+#testimonials {
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="6"><rect x="0" y="0" width="1" height="1" fill="black"/><rect x="3" y="3" width="1" height="1" fill="black"/></svg>');
+ padding: calc(2 * var(--base-grid));
+ width: 100%;
+ display: flex;
+ column-gap: calc(4 * var(--base-grid));
+ row-gap: calc(3 * var(--base-grid));
+ flex-wrap: wrap;
+
+ @media (max-width: 360px) {
+ padding: calc(2 * var(--base-grid)) var(--base-grid);
+ }
+
+ section {
+ flex: 1;
+ min-width: calc(17 * var(--base-grid));
+
+ @media (max-width: 360px) {
+ min-width: calc(100vw - 3 * var(--base-grid));
+ }
+ }
}
/* The Floating Window */
@@ -214,13 +325,13 @@ main {
}
.window {
+
.titlebar {
border-bottom: var(--border-width) solid #000;
- padding: calc(4 * var(--border-width)) calc(8 * var(--border-width));
+ padding: calc(3 * var(--border-width)) calc(8 * var(--border-width));
line-height: calc(9 * var(--border-width));
text-align: center;
- font-weight: 600;
- image-rendering: crisp-edges;
+ font-weight: 700;
background: repeating-linear-gradient(
0deg,
black,
@@ -245,26 +356,8 @@ main {
}
}
- &.pinned {
- width: calc(20 * var(--base-grid));
- position: absolute;
- bottom: 0;
- right: var(--base-grid);
- }
-
- &.free {
-
- }
-
.content {
- height: 0.01em;
- padding: 5px;
- transition: height 1s;
- }
-
- &[open] .content {
- overflow: hidden;
- height: 10lh;
+ padding: var(--base-grid);
}
hr.divider {
diff --git a/img/selfie.png b/img/selfie.png
new file mode 100644
index 0000000..5abfd3d
--- /dev/null
+++ b/img/selfie.png
Binary files differ
diff --git a/index.html b/index.html
index d29245d..6f2382f 100644
--- a/index.html
+++ b/index.html
@@ -14,6 +14,7 @@
<link rel="preload" href="/font/LibreCaslonCondensed[wdth,wght].woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/font/LibreCaslonCondensed-Italic[wght].woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/font/Ronzino-Medium.woff2" as="font" type="font/woff2" crossorigin>
+ <link rel="preload" href="/font/Ronzino-Bold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" type="text/css" href="/css/style.css">
<link rel="author" href="humans.txt">
@@ -31,43 +32,76 @@
services ✷</p>
</header>
<main>
- <section class="topic services">
+ <section id="introduction">
+ <section class="window cutoff-corners">
+ <header class="titlebar">
+ <span class="label">Welcome.</span>
+ </header>
+ <div class="content">
+ <img src="/img/selfie.png" alt="A pixel-art portrait of Rubén doing a peace sign and sticking his tongue out" />
+ <p>Howdy! I'm Rubén, a freelance full-stack software engineer based in Berlin. Looking for some help with your project? I might be able to help!</p>
+ </div>
+ </section>
+ </section>
+ <section id="services">
<section>
<h2>I can help you build.</h2>
<ul>
- <li>Websites that are <strong>fast</strong>, <strong>accessible</strong> and <strong>search engine optimized</strong>.</li>
- <li>Observable APIs and services with clear documentation that can be run at scale.</li>
- <li>Native macOS, iOS or ipadOS applications.</li>
+ <li><strong>Websites</strong> that are fast, accessible and search engine optimized.</li>
+ <li><strong>Native apps</strong> for iOS, iPadOS or macOS.</li>
+ <li><strong>Backend Services</strong> with great observability, clear documentation, and made to scale.</li>
+ <li><strong>Data Pipelines</strong> from tracking planning, to data warehouse extract-load-transform pipelines that give you accurate and actionable information.</li>
+ <li><strong>Infrastructure</strong> that can tie all your services, documented as code.</li>
</ul>
</section>
<section>
<h2>Optimize and improve.</h2>
<ul>
- <li>Analyze and reduce risk in your <strong>supply chain</strong> across different ecosystems like Javascript, Swift, Rust, or Python.</li>
+ <li><strong>Supply chain analysis</strong> to reduce risk from dependencies across different packaging ecosystems.</li>
<li><strong>Automate</strong> code quality and deployment.</li>
- <li>Reduce your overall cloud cost.</li>
+ <li><strong>Reduce cloud cost</strong> by optimizing your resource usage, plans and overall architecture.</li>
+ <li><strong>Optimize Large-Language-Model</strong> usage by creating custom tooling and Model Context Protocol (MCP) servers.</li>
</ul>
</section>
<section>
<h2>Or help your team go fast.</h2>
<ul>
+ <li>Bring your team up to speed with new technologies, architecture patterns or processes.</li>
<li>Bring product and engineering closer together.</li>
- <li>Professionalize or streamline your processes.</li>
+ <li><strong>Experimentation mindset</strong>, help your team learn how to design, execute, and interpret experiments.</li>
+ <li>Professionalize or streamline your processes by finding chokepoints and waste.</li>
</ul>
</section>
</section>
- <section class="topic skills">
- <h2>Aint that right!</h2>
+ <section id="skills">
+ <section class="textured">
+ <h2>Ain't that right!</h2>
+ <p>With over 25 years of experience, I've worked with big and small teams, ad-supported and sales-driven products, bootstrapped startups looking to launch, and established companies looking to scale up. I've worked with all sorts of stacks:</p>
+ <ul>
+ <li><strong>Languages:</strong> JavaScript, Rust, Ruby, Python, PHP, Swift, Objective-C.</li>
+ <li><strong>Cloud Providers:</strong> AWS, Scaleway, Cloudflare, Google Cloud, Azure.</li>
+ <li><strong>CI Systems:</strong> GitHub, Gitlab, CircleCI, TravisCI, Jenkins, Bitrise.</li>
+ <li><strong>Database Systems:</strong> PostgreSQL, MySQL/Aurora, Redis, MongoDB, Apache Cassandra, Snowflake.</li>
+ <li><strong>Analytics Software:</strong> Google Analytics, Amplitude, PostHog, .</li>
+ </ul>
+ </section>
+ <section class="window cutoff-corners pinned">
+ <header class="titlebar">
+ <span class="label">Get in touch.</span>
+ </header>
+ <div class="content">
+ <p>You can book a call to tell me about your project face to face. Or you if you prefer text, you can send me an e-mail!</p>
+ <button><label>Book a call.</label></button>
+ <a role="button" href="mailto:hello@ruben.bdr.sh?subject=Howdy%2C%20I%27d%20like%20to%20work%20with%20you%21&body=Hi%20Rub%C3%A9n%2C%0D%0A%0D%0AI%20saw%20the%20contact%20form%20on%20your%20website%20and%20would%20like%20to%20see%20if%20we%20can%20work%20together%20on%20my%20project%3A%0D%0A%0D%0A%3CTell%20me%20a%20bit%20about%20your%20project%20here%3E%0D%0A%0D%0ABest%2C%0D%0A%3CYour%20Name%3E"><label>Send an e-mail.</label></a>
+ </div>
+ </section>
+ </section>
+ <section id="testimonials">
+ <section class="textured">
+ <h2>But don't take my word for it.</h2>
+ <p>Here's what some lovely people have to say about me.</p>
+ </section>
</section>
</main>
- <aside>
- <details class="window cutoff-corners pinned">
- <summary class="titlebar">
- <span class="label">Get in touch.</span>
- </summary>
- <div class="content">Hello.</div>
- </details>
- </aside>
</body>
</html>
-