Compare commits

..

13 Commits

Author SHA1 Message Date
fa518379d1 Remove paragraph after orchestra
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 3m39s
2026-01-22 11:04:48 +10:30
d0cf6187c0 Remove top margin
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 3m13s
2026-01-22 10:49:33 +10:30
6132ebae45 Add sheet music page, some slight changes
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 20m17s
2026-01-22 10:36:19 +10:30
9335d19031 Make background colour consistent when page doesn't fully cover screen 2026-01-22 10:31:52 +10:30
ca6f0de553 Remove recognition page, adjust section on index
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 3m2s
2025-12-17 09:17:36 +10:30
b8b4ddd059 Animate player image
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 2m33s
2025-12-11 15:24:55 +10:30
4acbf3ef8a Add hover zoom to images in projects/MDX
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 2m45s
2025-12-11 11:11:38 +10:30
5a83282da4 Add blurred artwork to player if available
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 2m49s
2025-12-11 09:29:11 +10:30
7e887f8bb1 Update README.md to include note about CI/CD
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 12m12s
2025-12-10 09:05:33 +10:30
2666a680ab Wind orchestra, not just orchestra, is clearer
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 4m7s
2025-11-27 09:50:54 +10:30
16d14adb32 and
Some checks failed
Build and Deploy to Web Server / deploy (push) Has been cancelled
2025-11-27 09:49:01 +10:30
d714ed3e3b Minor fixes to about page
All checks were successful
Build and Deploy to Web Server / deploy (push) Successful in 4m31s
2025-11-27 09:42:22 +10:30
4caf5665be A tag on new line caused additional space
Some checks failed
Build and Deploy to Web Server / deploy (push) Has been cancelled
2025-11-27 09:39:48 +10:30
16 changed files with 219 additions and 72 deletions

View File

@@ -42,14 +42,14 @@ This website was built primarily with the following technologies:
1. Install prerequisites (Node.js)
2. Run `npm install`
3. From the root of the project directory, run `npm run dev` to start the development server which automatically refreshes on content changes
3. From the root of the project directory, run `npm run dev` to start the development server which automatically refreshes on content changes. Visual Studio Code will automatically deploy the development server when it opens.
## Building and Deploying
To build, as with most Astro projects, simply run `npm run build`, which currently outputs the built website to the `dist` folder.
Eventually, this website will automatically deploy via my custom-built deployment system and self-hosted server environment (todo!).
Changes made to this repository are automatically deployed via my custom-built CI/CD and self-hosted server environment.
## Show your support
You sharing my website is all the support I need.
However, if you'd like to support me in any other way, please feel free to get in touch!
However, if you'd like to support me in any other way or would like to work with me on a project, please feel free to get in touch!

View File

@@ -39,7 +39,7 @@ My hope was that this concert would help give these composers and these studios
Inevitably because of this vision, this year's concert again grew in scale and ambition, becoming the largest _Music With Motion_ event yet.
It was, to my knowledge, the largest live video game music concert ever held in Australia that focused exclusively on Australian games.
The concert showcased a talented ensemble that grew to 54 musicians and also featured live choir, guest soloists, all with real-time audio-visual synchronisation created just for this event (special thanks to Daytime Devs for the opening sequence!).
The concert showcased a talented ensemble that grew to 54 musicians and also featured live choir and guest soloists, all with real-time audio-visual synchronisation created just for this event (special thanks to Daytime Devs for the opening sequence!).
![Some of the Woodville Concert Band and Woodville High School Senior Choir on stage](/src/assets/img/projects/music-with-motion-down-under/nathan-cummins-music-with-motion-down-under-4.jpg)
@@ -141,7 +141,7 @@ Most importantly I'd like to thank my partner Camille, whose unwavering support
On a personal note, it took hundreds of hours to bring _Music With Motion: Down Under_ to life.
This concert was my way of supporting, uplifting, and giving back to the community that has shaped so much of my own creative path.
Seeing these works come alive with orchestra, and seeing the pride and joy on the faces of the composers, developers, the performers, and even the audience, made every moment worth it.
Seeing these works come alive with wind orchestra, and seeing the pride and joy on the faces of the composers, developers, the performers, and even the audience, made every moment worth it.
Thank you to everyone who attended, performed, collaborated, showcased, or was otherwise involved in some way.
I'm deeply grateful.

View File

@@ -7,7 +7,7 @@ const links: Link[] = [
{ href: "/", label: "Home" },
{ href: "/about/", label: "About" },
{ href: "/projects/", label: "Projects" },
{ href: "/recognition/", label: "Recognition" },
{ href: "/sheet-music/", label: "Sheet Music" },
{ href: "/contact/", label: "Contact" }
];

View File

@@ -13,8 +13,7 @@ const { award } = Astro.props as Props;
const { Content } = await render(award);
---
<div class="col-span-1">
<div class="bg-primary rounded text-white shadow">
<div class="bg-primary rounded text-white shadow">
<div class="p-2">
<div class="text-l font-bold">{award.data.title}</div>
<div class="text-sm italic">
@@ -26,5 +25,4 @@ const { Content } = await render(award);
<Content components={{ a: A }} />
</div>
</div>
</div>
</div>

View File

@@ -1 +1,5 @@
<h1 class="font-header text-3xl"><slot /></h1>
---
const { class: className, ...attrs } = Astro.props;
---
<h1 class:list={["font-header text-3xl", className]} {...attrs}><slot /></h1>

View File

@@ -1 +1,5 @@
<h2 class="font-header text-2xl"><slot /></h2>
---
const { class: className, ...attrs } = Astro.props;
---
<h2 class:list={["font-header text-2xl", className]} {...attrs}><slot /></h2>

View File

@@ -5,12 +5,19 @@ const { src, alt } = Astro.props;
import { getImageByPath } from "@lib/utils";
const image = getImageByPath(src);
// width of container is 896, width of image is set to 1344 to allow for hover zoom
---
{
image && (
<div class="my-8">
<Image src={image} alt={alt} width={896} />
<Image
src={image}
alt={alt}
width={1344}
class="transition ease-in-out lg:hover:scale-150"
/>
<div class="mt-2 block w-full text-center text-sm italic">{alt}</div>
</div>
)

View File

@@ -1,2 +1,5 @@
<span class="block p-0.5"><span class="text-primary pr-2">•</span><slot /></span
>
<li>
<span class="block p-0.5"
><span class="text-primary pr-2">•</span><slot /></span
>
</li>

View File

@@ -34,30 +34,45 @@ const initialQueue = await Promise.all(
};
})
);
const playerArtworkBlur = "10px";
const playerArtworkOpacity = 0.4;
---
<div
id="player"
class:list={[
"fixed right-0 bottom-0 left-0 z-100 bg-black shadow-lg/75 md:right-3 md:bottom-3 md:left-3 md:rounded",
"fixed right-0 bottom-0 left-0 z-100 overflow-hidden bg-black shadow-lg/75 md:right-3 md:bottom-3 md:left-3 md:rounded",
height
]}
transition:persist=""
transition:name="player"
transition:animate="none"
>
<div class="absolute inset-0 -z-90 overflow-hidden">
<div
id="player:artwork:background"
class="animate-bg-perlin absolute top-0 right-0 bottom-0 left-0 -z-90"
>
</div>
</div>
<div
id="player:time:progress"
class="relative top-0 right-0 left-0 m-0 h-2 w-full rounded-t bg-gray-900 p-0 hover:cursor-pointer"
class="relative top-0 right-0 left-0 m-0 h-2 w-full rounded-t p-0 hover:cursor-pointer"
>
<div
id="player:time:progress:background"
class="absolute top-0 left-0 m-0 h-full w-full bg-gray-900 p-0 opacity-50"
>
</div>
<div
id="player:time:progress:buffered"
class="absolute top-0 left-0 m-0 h-full bg-gray-700 p-0"
class="absolute top-0 left-0 m-0 h-full bg-gray-700 p-0 opacity-50"
>
</div>
<div
id="player:time:progress:played"
class="from-primary to-primary-50 absolute top-0 left-0 m-0 h-full bg-gradient-to-r p-0"
class="from-primary to-primary-50 absolute top-0 left-0 m-0 h-full bg-gradient-to-r p-0 opacity-100"
>
</div>
</div>
@@ -95,7 +110,10 @@ const initialQueue = await Promise.all(
<div class:list={[height, "bg-gray-900"]}></div>
<script is:inline src="/js/howler.min.js"></script>
<script is:inline define:vars={{ initialQueue }}>
<script
is:inline
define:vars={{ initialQueue, playerArtworkBlur, playerArtworkOpacity }}
>
/**
* Player class containing the state of our playlist and where we are in it.
* Includes all methods for playing, skipping, updating the display, etc.
@@ -126,6 +144,9 @@ const initialQueue = await Promise.all(
bar: document.getElementById("player:time:progress"),
buffered: document.getElementById("player:time:progress:buffered"),
played: document.getElementById("player:time:progress:played")
},
artwork: {
background: document.getElementById("player:artwork:background")
}
};
@@ -137,6 +158,18 @@ const initialQueue = await Promise.all(
Math.round(playlist[this.index].duration)
);
if (playlist[this.index].metadata.artwork) {
this.UI.artwork.background.style.backgroundImage = `url('${playlist[this.index].metadata.artwork.src}')`;
this.UI.artwork.background.style.backgroundSize = "cover";
this.UI.artwork.background.style.backgroundPosition = "center";
this.UI.artwork.background.style.filter = `blur(${playerArtworkBlur})`;
this.UI.artwork.background.style.opacity = playerArtworkOpacity;
} else {
this.UI.artwork.background.style.backgroundImage = "";
this.UI.artwork.background.style.filter = "";
this.UI.artwork.background.style.opacity = "0";
}
this.UI.controls.play.addEventListener("click", function () {
window.player.play();
});
@@ -218,6 +251,18 @@ const initialQueue = await Promise.all(
);
this.UI.progress.buffered.style.width = "0%";
if (data.metadata.artwork) {
this.UI.artwork.background.style.backgroundImage = `url('${data.metadata.artwork.src}')`;
this.UI.artwork.background.style.backgroundSize = "cover";
this.UI.artwork.background.style.backgroundPosition = "center";
this.UI.artwork.background.style.filter = `blur(${playerArtworkBlur})`;
this.UI.artwork.background.style.opacity = playerArtworkOpacity;
} else {
this.UI.artwork.background.style.backgroundImage = "";
this.UI.artwork.background.style.filter = "";
this.UI.artwork.background.style.opacity = "0";
}
// Keep track of the index we are currently playing.
this.index = index;
}

View File

@@ -37,5 +37,5 @@ const linkIsExternal: boolean =
/>
</sup>
)
}
</a>
}</a
>

View File

@@ -28,7 +28,7 @@ import MainHead from "@layouts/MainHead.astro";
<MainHead {title} {subtitle} {description} {image} />
<body class="flex min-h-svh flex-col">
<Navbar {navbarDisplay} />
<main class="grow">
<main class="grow bg-white dark:bg-gray-950">
<slot />
</main>
<Footer />

View File

@@ -3,6 +3,7 @@ import aboutImage from "@assets/img/about.jpg";
import conductingImage from "@assets/img/about/nathan-cummins-composer-orchestrator-conductor-conducting-1.jpg";
import generalImage from "@assets/img/about/nathan-cummins-composer-orchestrator-conductor-general-1.png";
import H2 from "@components/MDX/H2.astro";
import LI from "@components/MDX/LI.astro";
import Paragraph from "@components/Paragraph.astro";
import SectionTitle from "@components/SectionTitle.astro";
import TextLink from "@components/TextLink.astro";
@@ -64,8 +65,8 @@ import { Image } from "astro:assets";
video games is recognised for its distinctive voice and adaptability.</Paragraph
>
<Paragraph>Recent projects include:</Paragraph>
<ul class="list-disc pl-4">
<li>
<ul>
<LI>
<span class="font-bold"
><TextLink
href="/projects/video-game/dungeons-and-dining-tables/"
@@ -73,16 +74,16 @@ import { Image } from "astro:assets";
Dungeons and Dining Tables</TextLink
>:</span
> a cosy, highly orchestral score full of warmth and colour.
</li>
<li>
</LI>
<LI>
<span class="font-bold">Roc's Odyssey:</span> an edgy, symphonic metal
soundtrack blending excitement with orchestral grandeur.
</li>
<li>
</LI>
<LI>
<span class="font-bold">The Lion and the Mouse:</span> a narrative work
for orchestra (or wind orchestra) that aims to teach children about music
and the instruments of the orchestra.
</li>
</LI>
</ul>
<Paragraph
>Nathan thrives on tailoring music to story and gameplay, crafting
@@ -108,19 +109,19 @@ import { Image } from "astro:assets";
players can deliver their best performance.</Paragraph
>
<Paragraph>Recent projects include:</Paragraph>
<ul class="list-disc pl-4">
<li>
<ul>
<LI>
<span class="font-bold">Hollow Knight: Silksong:</span> orchestration
and typesetting for the score composed by <TextLink
href="https://composerlarkin.com/">Christopher Larkin</TextLink
>.
</li>
<li>
</LI>
<LI>
<span class="font-bold">Submerged: Hidden Depths:</span> typesetting
for the recording score composed by <TextLink
href="https://jeffvandyck.com/">Jeff van Dyck</TextLink
>.
</li>
</LI>
</ul>
</div>
</section>
@@ -130,7 +131,7 @@ import { Image } from "astro:assets";
<Paragraph
>Nathan is a versatile conductor with specialisations in concert
performance, video game music, and studio recording. He is one of
Australias leading directors of concerts featuring video game music,
Australia's leading directors of concerts featuring video game music,
and is equally at home on the podium of a symphonic performance or in
the precision-driven environment of a recording session.</Paragraph
>
@@ -158,14 +159,14 @@ import { Image } from "astro:assets";
>Nathan is also the Artistic Director of the <TextLink
href="https://www.woodvillecb.com.au/"
>Woodville Concert Band</TextLink
>, an active, diverse, and inclusive community ensemble of around 45
>, an active, diverse, and inclusive community ensemble of around 50
members. Under his direction, the band has become a cultural hub,
reflecting the motto “music played for the community, by the
community.” Through performances that engage 8,0009,000 community
community”. Through performances that engage 8,000-9,000 community
members annually, the ensemble promotes music education, fosters
inclusivity, and provides a distinctive cultural offering that
supports local industries and artists. Nathans leadership has been
instrumental in shaping the bands vision of accessibility, culture,
supports local industries and artists. Nathan's leadership has been
instrumental in shaping the band's vision of accessibility, culture,
and community over profit, while still maintaining high artistic
standards.</Paragraph
>

View File

@@ -174,26 +174,12 @@ const tracks = (
<section id="recognition" class="bg-white dark:bg-gray-950">
<div class="mx-auto max-w-4xl px-8 py-16 text-center">
<SectionTitle>Recognition</SectionTitle>
<div class="grid grid-cols-1 md:grid-cols-2">
<div
class="col-span-1 flex h-48 w-full flex-col items-center justify-center"
>
<Paragraph
>I am very grateful to have been recognised and awarded for my
work.</Paragraph
>I am very grateful to have been recognised and awarded for my work.</Paragraph
>
<a
href="/recognition/"
class="bg-primary text-md font-header hover:text-primary repeat hover:ring-primary mx-auto inline-block rounded px-6 py-3 font-light text-white uppercase drop-shadow-lg/75 transition hover:bg-white hover:ring-2"
>
Click here for more information
</a>
</div>
<div class="md-8 h-48 overflow-hidden scroll-smooth p-0">
<div
class="md-8 col-span-1 h-48 overflow-hidden scroll-smooth p-0 md:mt-0"
>
<div
class="animate-scrolling-awards m-0 mx-auto flex max-w-3xs flex-col space-y-8 p-0"
class="animate-scrolling-awards m-0 mx-auto flex max-w-md flex-col space-y-8 p-0"
>
{
awardsDoubled.map((award) => {
@@ -203,7 +189,6 @@ const tracks = (
</div>
</div>
</div>
</div>
</section>
<section id="fillerUntilServicesIsComplete" class="text-white">
<div class="flex h-96 w-full items-center justify-center">

View File

@@ -0,0 +1,80 @@
---
import H2 from "@components/MDX/H2.astro";
import LI from "@components/MDX/LI.astro";
import Paragraph from "@components/Paragraph.astro";
import SectionTitle from "@components/SectionTitle.astro";
import TextLink from "@components/TextLink.astro";
import MainLayout from "@layouts/MainLayout.astro";
---
<MainLayout title="Sheet Music">
<div class="w-full bg-white py-16 dark:bg-gray-950">
<section id="intro">
<div class="mx-auto max-w-4xl px-8 text-left">
<SectionTitle class="pb-8">Sheet Music</SectionTitle>
<Paragraph
>Sheet music for many of my pieces and orchestrations is available for
purchase or rent. If you are interested in sheet music for performance
or study, for the moment the simplest method to obtain it is to <TextLink
href="/contact/">contact me</TextLink
>.</Paragraph
>
<Paragraph
>This page mostly contains scores that I am often asked about or that
are from projects that I am involved with as composer. Some other
scores (such as the <TextLink
href="https://jeffvandyck.bandcamp.com/album/submerged-hidden-depths-original-soundtrack"
>recording score for <i>Submerged: Hidden Depths</i></TextLink
>
composed by <TextLink href="https://jeffvandyck.com/"
>Jeff van Dyck</TextLink
>, which I engraved) may be available through different means. If you
are looking for a piece that is not listed here, please feel free to <TextLink
href="/contact/">contact me</TextLink
>, it may still be available.</Paragraph
>
</div>
</section>
<section id="available">
<div class="mx-auto max-w-4xl px-8 text-left">
<H2 class="mb-4">Orchestra</H2>
<ul>
<LI>
<b>The Lion and the Mouse</b>
<ul class="ml-4">
<LI>2222, 4331, timp, harp, narrator, perc (x3), strings</LI>
</ul>
</LI>
<LI>
<b>Lampshade Grove (from Dungeons and Dining Tables)</b>
<ul class="ml-4">
<LI>2222, 4331, timp, harp, celeste (optional), perc, strings</LI>
<LI>2222, 4210, timp, percussion (x1), strings</LI>
</ul>
</LI>
</ul>
<H2 class="my-4">Wind Orchestra / Concert Band</H2>
<ul>
<LI>The Lion and the Mouse</LI>
<LI>Lampshade Grove (from Dungeons and Dining Tables)</LI>
<LI>The Couch Troll (from Dungeons and Dining Tables)</LI>
<LI>Kindlerest (from Dungeons and Dining Tables)</LI>
<LI>Gameplay Trailer (from Dungeons and Dining Tables)</LI>
<LI>Centenary Fanfare</LI>
<LI>Roc's Odyssey (from Roc's Odyssey)</LI>
<LI>Vulkan (from Roc's Odyssey)</LI>
<LI>Hydra (from Roc's Odyssey)</LI>
</ul>
<H2 class="my-4">String Quartet</H2>
<ul>
<LI>String Quartet No. 1</LI>
<LI>Aragornaise</LI>
</ul>
<H2 class="my-4">Choir</H2>
<ul>
<LI>Odi et Amo (SSAATTBB)</LI>
</ul>
</div>
</section>
</div>
</MainLayout>

View File

@@ -74,6 +74,26 @@
transform: translateY(1%);
}
}
--animate-bg-perlin: bg-perlin 60s linear infinite;
@keyframes bg-perlin {
0% {
transform: translateX(0%) scale(1);
}
25% {
transform: translateX(2%) scale(1.25);
}
50% {
transform: translateX(-2%) scale(1.02);
}
75% {
transform: translateX(1%) scale(1.18);
}
100% {
transform: translateX(0%) scale(1);
}
}
}
@layer base {