Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun run test
1 change: 1 addition & 0 deletions .stylelintrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"alpha-value-notation": null,
"at-rule-no-vendor-prefix": null,
"selector-max-id": 0,
"no-descending-specificity": null,
"declaration-no-important": true
}
}
15 changes: 2 additions & 13 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ addressed.
- [ ] logo animation should be vertically centered at top of page
- [ ] maybe indicate down to hint for scroll, z-index 9999
- [ ] experiment with lottiefile animation as a permanent background underneath content hmm
- [ ] 404 page
- [ ] 404 page - similar motion idea to homepage animation
- [ ] ideas list page
- [ ] broken link + other smoke tests
- [ ] idea individual pages (obv with coherent thoughts)
- [ ] for ideas pages, generate og images at build time - see: https://github.com/vercel/satori#documentation
- [ ] Workflow - each new project (especially the technical ones), get 2 posts: project page and idea/blog page announcing it. That then gets pushed to socials, etc. Tight workflow, and should help with SEO
Expand Down Expand Up @@ -79,16 +78,6 @@ addressed.

===

10k24 Studio Positioning:
Homepage (KPI framing):
"10k24 builds technical creative systems for organizations that need distinctive brands without traditional agency overhead.
We specialize in:
About page notes

Visual identity + technical implementation (design + code)
Generative design tools for creative teams
Brand systems for cultural organizations and startups

Recent work: International festival reaching 1M+ people across 21 countries, luxury interiors brand, wellness expansion, consumer tech launch."
About page (KPI story):
"Founded by Shakeel Mohamed, 10k24 combines 10 years of software engineering across developer tools, performance with graduate-level design training to create brand systems that work at scale.
Our approach: Technical rigor meets design intention. We build tools, not just deliverables."
2 changes: 2 additions & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[test]
root = "./tests"
8 changes: 4 additions & 4 deletions docs/projects/clock/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<title>10k24 Studio | Clocks</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="description" content="Clocks based on a 32x32 pixel grid.">
<meta name="author" content="TEN THOUSAND IDEAS, TWENTY-FOUR HOURS">
<meta name="robots" content="index, follow">
<meta name="theme-color" content="#000000">
Expand All @@ -15,14 +15,14 @@
<meta property="og:image" content="https://10k24.com/img/opengraph.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:description" content="" />
<meta property="og:description" content="Clocks based on a 32x32 pixel grid." />
<meta property="og:type" content="website" />
<meta property="og:locale" content="en_US" />
<meta property="og:site_name" content="10k24 Studio" />

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="10k24 Studio | Clocks" />
<meta name="twitter:description" content="" />
<meta name="twitter:description" content="Clocks based on a 32x32 pixel grid." />
<meta name="twitter:image" content="https://10k24.com/img/opengraph.png" />

<link rel="stylesheet" href="https://use.typekit.net/rli7dce.css">
Expand Down Expand Up @@ -105,7 +105,7 @@ <h1>Clocks</h1>
<!-- TODO: specify hero image so it can be different from cover img -->
<!-- TODO: copy, image, story -->

<p>Ticking down the year on a 32x32 pixel grid.</p>
<p>Clocks based on a 32x32 pixel grid.</p>

<div class="square-p5-container" data-sketch-file="clock" data-sketch-src="./clock.js"></div>

Expand Down
10 changes: 5 additions & 5 deletions docs/projects/midjourney/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ <h1>Midjourney</h1>

<div class="grid-2">
<div>
<p>Midjourney has received tremendous press since 2021, yet non-technical audiences are often discouraged by their visual communication. This project positions them to remain competitive in a rapidly growing AI landscape by making the brand more approachable.</p>
<p>Midjourney has received tremendous press since 2021, yet non-technical audiences are often discouraged by their visual communication. This project positions them to remain competitive in a rapidly growing AI landscape by making the identity more approachable.</p>
<br>
<p>The strategy draws from the founder’s quotes and mission statement. Light refraction serves as the central metaphor — symbolizing the expansive creativity their tools make possible. Brand colors connect across cultures, ages, and industries, distinguishing Midjourney from the sea of tech-company blue.</p>
<p>The strategy draws from the founder’s quotes and mission statement. Light refraction serves as the central metaphor — symbolizing the expansive creativity their tools make possible. Visual identity colors connect across cultures, ages, and industries, distinguishing Midjourney from the sea of tech-company blue.</p>
</div>
<div>
<p>The new logo is an evolution of the previous sailboat symbol — distilled to its simplest abstraction.</p>
Expand All @@ -115,13 +115,13 @@ <h1>Midjourney</h1>

<div class="grid-1">
<img src="img/midjourney-003.png" alt="" class="portfolio-img">
<p class="caption">The Sail. Through extensive identity exploration, this was the simplest abstraction of their sailboat logo.</p>
<p class="caption">The Sail. Through extensive logo exploration, this was the simplest abstraction of their sailboat logo.</p>
</div>

<div class="grid-2">
<div>
<img src="img/midjourney-007.png" alt="" class="portfolio-img">
<p class="caption">Brand colors emerged from light refraction, symbolizing expansive creativity possible with their&nbsp;products.</p>
<p class="caption">Visual identity colors emerged from light refraction, symbolizing expansive creativity possible with their&nbsp;products.</p>
</div>
<div>
<img src="img/midjourney-008.png" alt="" class="portfolio-img">
Expand All @@ -130,7 +130,7 @@ <h1>Midjourney</h1>
</div>

<div class="grid-1">
<img src="img/midjourney-009.png" alt="Logo family expressed through all brand colors: vertical lockup, icon, wordmark." class="portfolio-img">
<img src="img/midjourney-009.png" alt="Logo family expressed through all visual identity colors: vertical lockup, icon, wordmark." class="portfolio-img">
</div>

<div class="grid-2">
Expand Down
8 changes: 4 additions & 4 deletions docs/projects/planetary-society/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ <h1>Planetary Society</h1>

<div class="grid-2">
<div>
<p>The Planetary Society is a non-profit advocacy organization for space exploration, based in Pasadena, California. The identity expands the audience beyond enthusiasts — exploring the profound human experience of our relationship to the cosmos. A primary serif typeface gives every brand touchpoint an elevated, timeless feeling. Removing “The” from the name created a cleaner shorthand.</p>
<p>The Planetary Society is a non-profit advocacy organization for space exploration, based in Pasadena, California. The identity expands the audience beyond enthusiasts — exploring the profound human experience of our relationship to the cosmos. A primary serif typeface gives every touchpoint an elevated, timeless feeling. Removing “The” from the name created a cleaner shorthand.</p>
</div>
<div>
<p>A special brand style was designed for the Society’s 45th anniversary, including a custom modular variable typeface inspired by planetary orbits. The anniversary identity envisions a weekend celebration on Catalina Island for members and donors.</p>
<p>A special campaign style was designed for the Society’s 45th anniversary, including a custom modular variable typeface inspired by planetary orbits. The anniversary identity envisions a weekend celebration on Catalina Island for members and donors.</p>
</div>
</div>

Expand All @@ -125,7 +125,7 @@ <h1>Planetary Society</h1>
</div>
<div>
<img src="img/Planetary_Society_ID_overview.png" alt="" class="portfolio-img">
<p class="caption">Overview of the identity system. A serif typeface breaks the retro-sci-fi standard in aerospace, giving all brand messaging a timeless, contemplative quality.</p>
<p class="caption">Overview of the identity system. A serif typeface breaks the retro-sci-fi standard in aerospace, giving all messaging a timeless, contemplative quality.</p>
</div>
</div>

Expand Down Expand Up @@ -159,7 +159,7 @@ <h1>Planetary Society</h1>
<hr>
<p><strong>45th Anniversary Campaign</strong></p>
<br>
<p class="caption">The 45th anniversary identity carries a distinct brand and typographic voice. The highlight of the year would be a retreat on Catalina Island for members and donors, “Under the Stars.”</p>
<p class="caption">The 45th anniversary identity carries a distinct look and typographic voice. The highlight of the year would be a retreat on Catalina Island for members and donors, “Under the Stars.”</p>

<div class="grid-1">
<img src="img/TPS - 4.png" alt="" class="portfolio-img">
Expand Down
2 changes: 1 addition & 1 deletion docs/projects/salgirah-festival/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ <h1>Salgirah Festival</h1>

<br>
<hr>
<p><strong>Global Brand Activation</strong></p>
<p><strong>Global Activation</strong></p>
<br>

<div class="grid-1">
Expand Down
12 changes: 0 additions & 12 deletions docs/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ a {
text-decoration: none;
}

/* TODO: bring back once project pages are added */
a:hover {
text-decoration: underline;
text-underline-offset: 0.25rem;
Expand Down Expand Up @@ -179,8 +178,6 @@ section {

.section-item {
max-width: 50%;

/* margin-bottom: 1.5rem; */
margin-bottom: 4rem;
}

Expand All @@ -191,7 +188,6 @@ section {
}

.hero {
/*min-height: 100vh;*/
margin-top: -4rem;
}

Expand Down Expand Up @@ -249,10 +245,6 @@ h3.project-title, h3.idea-title {
text-decoration: none;
}

/* h3.project-title:hover {
text-decoration: underline;
} */

p.project-meta, p.idea-meta {
margin-top: 0.125rem;
margin-bottom: 0.125rem;
Expand All @@ -271,10 +263,6 @@ p.project-meta, p.idea-meta {
max-width: 60vw;
}

.portfolio-img {
width: 100%;
}

.video-16-9 {
width: 100%;
height: auto;
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
"lint:fix": "bunx stylelint --fix src/*.css",
"fix": "bun run lint:fix",
"optimize": "node scripts/optimize.js",
"test:words": "bunx cspell lint 'docs/**/*.html' --no-progress --no-summary --quiet && echo 'test:words: clean'",
"test": "bun run test:words"
"pretest": "bun run build && bun run lint",
"posttest": "bunx cspell lint 'docs/**/*.html' --no-progress --no-summary --quiet && echo 'posttest: clean'",
"test": "bun test"
},
"private": true,
"devDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion src/projects/clock/index.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ tags:
- creative coding

cover: cover.png
description: "Clocks based on a 32x32 pixel grid."
media: Creative Coding
location: Los Angeles, CA

Expand All @@ -17,6 +18,6 @@ hideCover: false
<!-- TODO: specify hero image so it can be different from cover img -->
<!-- TODO: copy, image, story -->

<p>Ticking down the year on a 32x32 pixel grid.</p>
<p>Clocks based on a 32x32 pixel grid.</p>

{% include "_includes/partials/square-p5-sketch", sketch:"./clock.js" %}
10 changes: 5 additions & 5 deletions src/projects/midjourney/index.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ client: Conceptual

<div class="grid-2">
<div>
<p>Midjourney has received tremendous press since 2021, yet non-technical audiences are often discouraged by their visual communication. This project positions them to remain competitive in a rapidly growing AI landscape by making the brand more approachable.</p>
<p>Midjourney has received tremendous press since 2021, yet non-technical audiences are often discouraged by their visual communication. This project positions them to remain competitive in a rapidly growing AI landscape by making the identity more approachable.</p>
<br>
<p>The strategy draws from the founder’s quotes and mission statement. Light refraction serves as the central metaphor — symbolizing the expansive creativity their tools make possible. Brand colors connect across cultures, ages, and industries, distinguishing Midjourney from the sea of tech-company blue.</p>
<p>The strategy draws from the founder’s quotes and mission statement. Light refraction serves as the central metaphor — symbolizing the expansive creativity their tools make possible. Visual identity colors connect across cultures, ages, and industries, distinguishing Midjourney from the sea of tech-company blue.</p>
</div>
<div>
<p>The new logo is an evolution of the previous sailboat symbol — distilled to its simplest abstraction.</p>
Expand All @@ -23,13 +23,13 @@ client: Conceptual

<div class="grid-1">
<img src="img/midjourney-003.png" alt="" class="portfolio-img">
<p class="caption">The Sail. Through extensive identity exploration, this was the simplest abstraction of their sailboat logo.</p>
<p class="caption">The Sail. Through extensive logo exploration, this was the simplest abstraction of their sailboat logo.</p>
</div>

<div class="grid-2">
<div>
<img src="img/midjourney-007.png" alt="" class="portfolio-img">
<p class="caption">Brand colors emerged from light refraction, symbolizing expansive creativity possible with their&nbsp;products.</p>
<p class="caption">Visual identity colors emerged from light refraction, symbolizing expansive creativity possible with their&nbsp;products.</p>
</div>
<div>
<img src="img/midjourney-008.png" alt="" class="portfolio-img">
Expand All @@ -38,7 +38,7 @@ client: Conceptual
</div>

<div class="grid-1">
<img src="img/midjourney-009.png" alt="Logo family expressed through all brand colors: vertical lockup, icon, wordmark." class="portfolio-img">
<img src="img/midjourney-009.png" alt="Logo family expressed through all visual identity colors: vertical lockup, icon, wordmark." class="portfolio-img">
</div>

<div class="grid-2">
Expand Down
8 changes: 4 additions & 4 deletions src/projects/planetary-society/index.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ client: The Planetary Society (proposed)

<div class="grid-2">
<div>
<p>The Planetary Society is a non-profit advocacy organization for space exploration, based in Pasadena, California. The identity expands the audience beyond enthusiasts — exploring the profound human experience of our relationship to the cosmos. A primary serif typeface gives every brand touchpoint an elevated, timeless feeling. Removing “The” from the name created a cleaner shorthand.</p>
<p>The Planetary Society is a non-profit advocacy organization for space exploration, based in Pasadena, California. The identity expands the audience beyond enthusiasts — exploring the profound human experience of our relationship to the cosmos. A primary serif typeface gives every touchpoint an elevated, timeless feeling. Removing “The” from the name created a cleaner shorthand.</p>
</div>
<div>
<p>A special brand style was designed for the Society’s 45th anniversary, including a custom modular variable typeface inspired by planetary orbits. The anniversary identity envisions a weekend celebration on Catalina Island for members and donors.</p>
<p>A special campaign style was designed for the Society’s 45th anniversary, including a custom modular variable typeface inspired by planetary orbits. The anniversary identity envisions a weekend celebration on Catalina Island for members and donors.</p>
</div>
</div>

Expand All @@ -31,7 +31,7 @@ client: The Planetary Society (proposed)
</div>
<div>
<img src="img/Planetary_Society_ID_overview.png" alt="" class="portfolio-img">
<p class="caption">Overview of the identity system. A serif typeface breaks the retro-sci-fi standard in aerospace, giving all brand messaging a timeless, contemplative quality.</p>
<p class="caption">Overview of the identity system. A serif typeface breaks the retro-sci-fi standard in aerospace, giving all messaging a timeless, contemplative quality.</p>
</div>
</div>

Expand Down Expand Up @@ -65,7 +65,7 @@ client: The Planetary Society (proposed)
<hr>
<p><strong>45th Anniversary Campaign</strong></p>
<br>
<p class="caption">The 45th anniversary identity carries a distinct brand and typographic voice. The highlight of the year would be a retreat on Catalina Island for members and donors, “Under the Stars.”</p>
<p class="caption">The 45th anniversary identity carries a distinct look and typographic voice. The highlight of the year would be a retreat on Catalina Island for members and donors, “Under the Stars.”</p>

<div class="grid-1">
<img src="img/TPS - 4.png" alt="" class="portfolio-img">
Expand Down
2 changes: 1 addition & 1 deletion src/projects/salgirah-festival/index.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ client: The Ismaili Community

<br>
<hr>
<p><strong>Global Brand Activation</strong></p>
<p><strong>Global Activation</strong></p>
<br>

<div class="grid-1">
Expand Down
12 changes: 0 additions & 12 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ a {
text-decoration: none;
}

/* TODO: bring back once project pages are added */
a:hover {
text-decoration: underline;
text-underline-offset: 0.25rem;
Expand Down Expand Up @@ -179,8 +178,6 @@ section {

.section-item {
max-width: 50%;

/* margin-bottom: 1.5rem; */
margin-bottom: 4rem;
}

Expand All @@ -191,7 +188,6 @@ section {
}

.hero {
/*min-height: 100vh;*/
margin-top: -4rem;
}

Expand Down Expand Up @@ -249,10 +245,6 @@ h3.project-title, h3.idea-title {
text-decoration: none;
}

/* h3.project-title:hover {
text-decoration: underline;
} */

p.project-meta, p.idea-meta {
margin-top: 0.125rem;
margin-bottom: 0.125rem;
Expand All @@ -271,10 +263,6 @@ p.project-meta, p.idea-meta {
max-width: 60vw;
}

.portfolio-img {
width: 100%;
}

.video-16-9 {
width: 100%;
height: auto;
Expand Down
35 changes: 35 additions & 0 deletions tests/smoke/data.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { describe, expect, test } = require("bun:test");
const { readFileSync } = require("node:fs");
const { resolve, join } = require("node:path");

const DATA_DIR = resolve(__dirname, "../..", "src/_data");

function readJson(filename) {
return JSON.parse(readFileSync(join(DATA_DIR, filename), "utf8"));
}

describe("metadata.json", () => {
const data = readJson("metadata.json");

test("baseURL is a non-empty string", () => {
expect(typeof data.baseURL).toBe("string");
expect(data.baseURL.length).toBeGreaterThan(0);
});

test("author.name is a non-empty string", () => {
expect(typeof data.author?.name).toBe("string");
expect(data.author.name.length).toBeGreaterThan(0);
});

test("author.email is a non-empty string", () => {
expect(typeof data.author?.email).toBe("string");
expect(data.author.email.length).toBeGreaterThan(0);
});

test("social links are non-empty strings", () => {
for (const [key, value] of Object.entries(data.social || {})) {
expect(typeof value, `social.${key} must be a string`).toBe("string");
expect(value.length, `social.${key} must not be empty`).toBeGreaterThan(0);
}
});
});
Loading
Loading