update blog post to include hugo specific front matter
This commit is contained in:
277
POST.md
Normal file
277
POST.md
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
---
|
||||||
|
title: "Mastering Strudel: A Reproducible Development Environment with Nix"
|
||||||
|
date: 2025-09-27T12:00:00+02:00
|
||||||
|
draft: false
|
||||||
|
tags: ["strudel", "nix", "development", "live-coding"]
|
||||||
|
categories: ["Development"]
|
||||||
|
build:
|
||||||
|
render: never
|
||||||
|
list: never
|
||||||
|
publishResources: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# Mastering Strudel: A Reproducible Development Environment with Nix
|
||||||
|
|
||||||
|
Strudel is a fascinating JavaScript-based live coding environment that brings the power of TidalCycles to the web. As developers and musicians exploring algorithmic music composition, we've discovered that setting up a proper development environment is crucial for productive work. In this post, we'll dive deep into our Nix-based setup that makes Strudel development reproducible, reliable, and collaborative.
|
||||||
|
|
||||||
|
## Why Nix for Strudel Development?
|
||||||
|
|
||||||
|
Traditional development environments often suffer from the "works on my machine" syndrome. Dependencies drift, versions conflict, and onboarding new contributors becomes a chore. Nix solves these problems by providing declarative, reproducible environments.
|
||||||
|
|
||||||
|
Our Strudel development setup uses:
|
||||||
|
|
||||||
|
- **Nix Flakes** for pinned, reproducible dependencies
|
||||||
|
- **Git submodules** to track the official Strudel repository
|
||||||
|
- **Makefile** for convenient command shortcuts
|
||||||
|
- **Comprehensive guidelines** for AI-assisted development
|
||||||
|
|
||||||
|
## Getting Started: The Complete Setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
Before diving in, ensure you have:
|
||||||
|
- [Nix](https://nixos.org/download.html) package manager (version 2.4+)
|
||||||
|
- Git for version control
|
||||||
|
|
||||||
|
### Step-by-Step Setup
|
||||||
|
|
||||||
|
1. **Clone the repository**:
|
||||||
|
```bash
|
||||||
|
git clone <your-strudel-dev-repo-url>
|
||||||
|
cd strudel
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Initialize git submodules**:
|
||||||
|
```bash
|
||||||
|
make submodules-init submodules-update
|
||||||
|
```
|
||||||
|
This pulls in the official Strudel codebase as a submodule in the `src/` directory.
|
||||||
|
|
||||||
|
3. **Enter the development environment**:
|
||||||
|
```bash
|
||||||
|
make shell
|
||||||
|
```
|
||||||
|
This launches a Nix shell with Node.js 20, pnpm, and git pre-configured.
|
||||||
|
|
||||||
|
4. **Install dependencies**:
|
||||||
|
```bash
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
This runs `pnpm install` within the Nix environment, ensuring consistent package versions.
|
||||||
|
|
||||||
|
5. **Start the development server**:
|
||||||
|
```bash
|
||||||
|
make dev
|
||||||
|
```
|
||||||
|
The Strudel REPL will be available at `http://localhost:5173`.
|
||||||
|
|
||||||
|
## Understanding the Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
strudel/
|
||||||
|
├── src/ # Strudel codebase (git submodule)
|
||||||
|
├── AGENTS.md # Guidelines for AI assistants
|
||||||
|
├── Makefile # Development shortcuts
|
||||||
|
├── flake.nix # Nix development environment
|
||||||
|
├── flake.lock # Nix flake lockfile
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
The `src/` directory contains the actual Strudel monorepo as a git submodule. This approach ensures we always work with a specific, tested version of Strudel while keeping our development environment separate.
|
||||||
|
|
||||||
|
## Workflow Mastery with Makefile
|
||||||
|
|
||||||
|
Our Makefile provides a clean interface for all development tasks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make help # Show all available targets
|
||||||
|
make update # Initialize and update git submodules
|
||||||
|
make install # Install dependencies
|
||||||
|
make dev # Start development server
|
||||||
|
make build # Build the project
|
||||||
|
make test # Run tests
|
||||||
|
make lint # Run linter
|
||||||
|
make format # Format code
|
||||||
|
make check # Run all checks
|
||||||
|
make clean # Clean build artifacts
|
||||||
|
make shell # Enter Nix development shell
|
||||||
|
```
|
||||||
|
|
||||||
|
Every command automatically runs within the Nix environment, ensuring consistency across different machines and operating systems.
|
||||||
|
|
||||||
|
## Git Submodules: The Right Way
|
||||||
|
|
||||||
|
Working with git submodules can be tricky, but we've established best practices:
|
||||||
|
|
||||||
|
### Common Pitfalls and Solutions
|
||||||
|
|
||||||
|
**Problem**: `git status` shows submodule changes after installing dependencies.
|
||||||
|
|
||||||
|
**Solution**: Dependencies like `node_modules/` are properly ignored in the submodule's `.gitignore`. However, some files may have permission changes during installation (like executable scripts). To handle this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check what changed
|
||||||
|
cd src && git status
|
||||||
|
|
||||||
|
# Discard unintended changes
|
||||||
|
git submodule foreach git checkout -- .
|
||||||
|
|
||||||
|
# Reset submodule to clean state
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Principle**: Treat submodules as read-only for local changes. If you need to modify Strudel itself, commit changes to the upstream repository first.
|
||||||
|
|
||||||
|
## AI-Assisted Development: Guidelines for Success
|
||||||
|
|
||||||
|
Our `AGENTS.md` document provides comprehensive guidelines for AI assistants working with Strudel. Here are the critical points:
|
||||||
|
|
||||||
|
### Strudel is NOT JavaScript
|
||||||
|
|
||||||
|
Despite being built with JavaScript, Strudel uses its own pattern-based syntax:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// ✅ CORRECT - Direct pattern composition
|
||||||
|
$: sound("bd*4")
|
||||||
|
$: sound("~ sd ~ sd")
|
||||||
|
$: sound("hh*8").gain(0.3)
|
||||||
|
|
||||||
|
// ❌ WRONG - JavaScript-style approach
|
||||||
|
const kick = sound("bd*4");
|
||||||
|
const snare = sound("~ sd ~ sd");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Essential Syntax Patterns
|
||||||
|
|
||||||
|
**Parallel Patterns**: Use multiple `$:` lines for simultaneous playback
|
||||||
|
**Muting**: Prefix with `_` to silence patterns during live performance
|
||||||
|
**Mini-notation**: `"bd ~ sd ~"` for rhythmic patterns
|
||||||
|
**Scale-based Composition**: Use `n("0 2 4 6").scale("C:minor")` instead of manual note names
|
||||||
|
|
||||||
|
### Sound Sources and Effects
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Drum samples
|
||||||
|
$: sound("bd sd hh oh")
|
||||||
|
|
||||||
|
// Synthesizers with scales
|
||||||
|
$: n("0 2 4 6").scale("C:minor").sound("sawtooth")
|
||||||
|
|
||||||
|
// Live effects
|
||||||
|
$: sound("bd*4").lpf(sine.range(200, 2000).slow(8))
|
||||||
|
```
|
||||||
|
|
||||||
|
### Live Performance Best Practices
|
||||||
|
|
||||||
|
- Each `$:` line is independently controllable
|
||||||
|
- Use `_$:` to mute sections during performance
|
||||||
|
- Include modulation for evolving sounds
|
||||||
|
- Keep patterns readable for live modification
|
||||||
|
|
||||||
|
## Nix Flake Configuration Deep Dive
|
||||||
|
|
||||||
|
Our `flake.nix` provides a robust development environment:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
description = "Strudel development environment";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
nodejs_20
|
||||||
|
pnpm
|
||||||
|
git
|
||||||
|
];
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
echo "Strudel development environment loaded"
|
||||||
|
echo "Node.js: $(node --version)"
|
||||||
|
echo "pnpm: $(pnpm --version)"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This configuration:
|
||||||
|
- Pins Nixpkgs to version 25.05 for reproducibility
|
||||||
|
- Provides Node.js 20 and pnpm for package management
|
||||||
|
- Includes git for version control operations
|
||||||
|
- Shows version information on shell entry
|
||||||
|
|
||||||
|
## Contributing and Best Practices
|
||||||
|
|
||||||
|
When contributing to Strudel development:
|
||||||
|
|
||||||
|
- Follow the guidelines in `AGENTS.md` for AI-assisted work
|
||||||
|
- Use lowercase commit messages
|
||||||
|
- Ensure all changes pass `make check`
|
||||||
|
- Test thoroughly before submitting
|
||||||
|
|
||||||
|
## Troubleshooting Common Issues
|
||||||
|
|
||||||
|
### Submodule Problems
|
||||||
|
```bash
|
||||||
|
make update # Reinitialize submodules
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependency Issues
|
||||||
|
```bash
|
||||||
|
make clean && make install # Fresh dependency installation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nix Issues
|
||||||
|
Ensure Nix is installed and up-to-date. On Linux:
|
||||||
|
```bash
|
||||||
|
sh <(curl -L https://nixos.org/nix/install) --daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
## The Power of Reproducible Environments
|
||||||
|
|
||||||
|
This Nix-based setup eliminates common development headaches:
|
||||||
|
|
||||||
|
- **Zero configuration drift**: Everyone gets identical environments
|
||||||
|
- **Easy onboarding**: New contributors can start coding immediately
|
||||||
|
- **Version pinning**: Dependencies are locked to specific versions
|
||||||
|
- **Cross-platform compatibility**: Works on Linux, macOS, and Windows (via WSL)
|
||||||
|
|
||||||
|
## Live Coding with Strudel: A Glimpse
|
||||||
|
|
||||||
|
Once set up, you can start creating algorithmic music immediately:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Basic beat
|
||||||
|
$: sound("bd*4").gain(0.8)
|
||||||
|
$: sound("~ sd ~ sd").gain(0.7)
|
||||||
|
$: sound("hh*8").gain(0.3)
|
||||||
|
|
||||||
|
// Melodic elements
|
||||||
|
$: n("0 ~ 2 ~ 4 ~ 6 ~").scale("C2:minor").sound("sawtooth").lpf(1200)
|
||||||
|
$: n("~ 0 ~ 2 ~ 4 ~ 6").scale("C4:minor").sound("piano").room(0.6)
|
||||||
|
|
||||||
|
// Live effects
|
||||||
|
_$: sound("bd*4").lpf(sine.range(200, 2000).slow(8)) // muted filter sweep
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Setting up a proper development environment for Strudel isn't just about getting code to run—it's about creating a sustainable, collaborative workflow that scales. Our Nix-based approach, combined with careful submodule management and comprehensive guidelines, provides a solid foundation for both individual exploration and team development.
|
||||||
|
|
||||||
|
Whether you're a seasoned live coder or just starting your algorithmic music journey, this environment ensures you can focus on what matters most: creating amazing sounds.
|
||||||
|
|
||||||
|
The Strudel community welcomes contributors at all levels. Check out the [official Strudel website](https://strudel.cc/) and [workshop](https://strudel.cc/workshop/) to learn more, and join us in pushing the boundaries of live coding music!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*This post is part of our series on reproducible development environments. Stay tuned for more insights into modern software development practices.*
|
||||||
Reference in New Issue
Block a user