Skip to content

Conversation

@pinin4fjords
Copy link
Collaborator

@pinin4fjords pinin4fjords commented Oct 16, 2025

Summary

This side quest teaches why workflow managers exist by having learners experience the limitations of scripting approaches firsthand, then see how Nextflow solves each problem.

Pedagogical Approach

Quality Framework

The tutorial opens by defining 7 production-quality standards for pipelines:

  • Reproducibility
  • Software management (per-task isolation)
  • Scalability
  • Efficient parallelization
  • Resource awareness
  • Failure recovery
  • Portability

Learners then try to achieve these with scripts (Part 1) and see how workflow managers handle them (Part 2).

Part 1: Scripts

Learners build an RNA-seq pipeline in bash, progressively hitting limitations:

  • Tool installation friction (conda conflicts, manual setup)
  • Sequential processing waste
  • Parallelization complexity (& and wait, no resource limits)
  • No failure recovery
  • Portability issues (cluster rewrites)

Uses starter files with TODOs - learners fill in tool commands, not boilerplate.

Part 2: Nextflow

Learners rebuild the same pipeline, with explicit callbacks to Part 1:

  • "Remember installing tools with conda? Here's container"
  • "Remember & and wait? Nextflow infers parallelization from data flow"
  • "Remember checkpoint logic? Here's -resume"

Includes a note that this isn't a proper Nextflow tutorial - directs to Hello Nextflow for that.

Before/After Blocks

Every code change uses tabbed Before/After blocks showing exactly what changes, with hl_lines highlighting the new/modified lines.

Key Points

  • Not bash-specific: Explicitly notes the same issues apply to Python, R, or any scripting approach
  • Software management: Emphasizes per-task isolation (each process gets its own container), not just version locking
  • Scalability: Scripts hit limits on one machine and need rewrites for cluster; Nextflow scales with config change
  • Standardization: Workflow managers are established tools with transferable skills and communities

Files

Documentation

  • docs/side_quests/workflow_management_fundamentals.md - Main tutorial with Before/After blocks

Starter Files (with TODOs/placeholders)

  • side-quests/workflow_management_fundamentals/bash/ - Bash starter scripts
  • side-quests/workflow_management_fundamentals/nextflow/ - Nextflow starter files with ??? placeholders
  • side-quests/workflow_management_fundamentals/data/samples.csv - Real RNA-seq test data

Solutions

  • side-quests/solutions/workflow_management_fundamentals/ - Complete working versions

Testing

  • Nextflow solution tested in Docker container (all 10 tasks complete successfully)
  • Documentation validated for heading numbering, admonitions, highlight accuracy

🤖 Generated with Claude Code

This side quest demonstrates the benefits of workflow management
systems by having users progressively build a bash script, experience
its limitations firsthand, then see how Nextflow solves each problem.

Key features:
- Progressive hands-on approach: users build bash scripts incrementally
- Experience problems before seeing solutions (sequential processing,
  resource conflicts, crashes, environment issues, no visibility)
- Clear before/after comparisons with concrete time savings
- Interactive exercises converting bash to Nextflow
- Uses bacterial genome analysis as single exemplar throughout
- Follows groovy_essentials conventions (tabs, console examples, etc.)

Files added:
- docs/side_quests/workflow_management_fundamentals.md (main tutorial)
- side-quests/workflow_management_fundamentals/ (working examples)
  - process_samples.sh (bash script version)
  - main.nf (Nextflow workflow)
  - modules/ (modular process definitions)
  - data/samples.csv (sample metadata)
  - nextflow.config (configuration examples)

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@netlify
Copy link

netlify bot commented Oct 16, 2025

Deploy Preview for nextflow-training ready!

Name Link
🔨 Latest commit a41659b
🔍 Latest deploy log https://app.netlify.com/projects/nextflow-training/deploys/696778d8f32238000833b001
😎 Deploy Preview https://deploy-preview-679--nextflow-training.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@pinin4fjords pinin4fjords marked this pull request as draft October 16, 2025 15:25
- Move solution files to solutions/ subdirectory so learners start fresh
- Add placeholder FASTQ files in data/reads/ (referenced in samples.csv)
- Add Exercise 5 for QUAST module (was used but undocumented)
- Fix hl_lines in Exercise 3: "3 17" → "4 20" (highlight FASTP additions)
- Fix hl_lines in Exercise 4: "4 21" → "5 22" (highlight SPADES additions)
- Update tree output to show actual directory structure
- Add tip about solutions directory for stuck learners
- Update README with new structure and usage instructions
- Remove extra emit:graph from spades.nf to match docs
- Remove singularity.enabled=false from config to match docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Jan 12, 2026

Nextflow linting complete!

❌ 4 files had 21 errors
✅ 170 files had no errors
🔧 153 files would be changed by auto-formatting

💡 Tip: Click filename locations to go directly to that code.

View all 21 issues
Type Location Message
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:11:1 Invalid include source: '/home/runner/work/training/training/hello-nextflow/solutions/5-hello-containers/modules/sayHello.nf'
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:12:1 Invalid include source: '/home/runner/work/training/training/hello-nextflow/solutions/5-hello-containers/modules/convertToUpper.nf'
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:13:1 Invalid include source: '/home/runner/work/training/training/hello-nextflow/solutions/5-hello-containers/modules/collectGreetings.nf'
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:24:5 sayHello is not defined
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:27:5 convertToUpper is not defined
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:27:20 sayHello is not defined
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:30:5 collectGreetings is not defined
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:30:22 convertToUpper is not defined
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:33:5 collectGreetings is not defined
Error hello-nextflow/solutions/5-hello-containers/hello-containers-2.nf:36:11 collectGreetings is not defined
Error hello-nf-core/solutions/core-hello-part2/nextflow.config:154:17 Invalid include source: '/home/runner/work/training/training/hello-nf-core/solutions/core-hello-part2/conf/test_full.config'
Error side-quests/solutions/workflows_of_workflows/workflows/greeting.nf:1:1 Invalid include source: '/home/runner/work/training/training/side-quests/solutions/workflows_of_workflows/modules/validate_name.nf'
Error side-quests/solutions/workflows_of_workflows/workflows/greeting.nf:2:1 Invalid include source: '/home/runner/work/training/training/side-quests/solutions/workflows_of_workflows/modules/say_hello.nf'
Error side-quests/solutions/workflows_of_workflows/workflows/greeting.nf:3:1 Invalid include source: '/home/runner/work/training/training/side-quests/solutions/workflows_of_workflows/modules/timestamp_greeting.nf'
Error side-quests/solutions/workflows_of_workflows/workflows/greeting.nf:11:24 VALIDATE_NAME is not defined
Error side-quests/solutions/workflows_of_workflows/workflows/greeting.nf:12:24 SAY_HELLO is not defined
Error side-quests/solutions/workflows_of_workflows/workflows/greeting.nf:13:26 TIMESTAMP_GREETING is not defined
Error side-quests/solutions/workflows_of_workflows/workflows/transform.nf:1:1 Invalid include source: '/home/runner/work/training/training/side-quests/solutions/workflows_of_workflows/modules/say_hello_upper.nf'
Error side-quests/solutions/workflows_of_workflows/workflows/transform.nf:2:1 Invalid include source: '/home/runner/work/training/training/side-quests/solutions/workflows_of_workflows/modules/reverse_text.nf'
Error side-quests/solutions/workflows_of_workflows/workflows/transform.nf:10:20 SAY_HELLO_UPPER is not defined
Error side-quests/solutions/workflows_of_workflows/workflows/transform.nf:11:23 REVERSE_TEXT is not defined
View formatting changes
FileDiff
hello-nextflow/solutions/1-hello-world/hello-world-3.nf
View
@@ -8,7 +8,7 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     output:
-        path 'output.txt'
+    path 'output.txt'
 
     script:
     """
hello-nextflow/solutions/1-hello-world/hello-world-4.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path 'output.txt'
+    path 'output.txt'
 
     script:
     """
-    echo '$greeting' > output.txt
+    echo '${greeting}' > output.txt
... (truncated)
hello-nextflow/solutions/2-hello-channels/hello-channels-1.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path 'output.txt'
+    path 'output.txt'
 
     script:
     """
-    echo '$greeting' > output.txt
+    echo '${greeting}' > output.txt
... (truncated)
hello-nextflow/solutions/2-hello-channels/hello-channels-2.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/2-hello-channels/hello-channels-3.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/2-hello-channels/hello-channels-4.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/3-hello-workflow/hello-workflow-1.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/3-hello-workflow/hello-workflow-2.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/3-hello-workflow/hello-workflow-3.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/3-hello-workflow/hello-workflow-4.nf
View
@@ -8,14 +8,14 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/4-hello-modules/hello-modules-2.nf
View
@@ -8,14 +8,14 @@ process convertToUpper {
     publishDir 'results', mode: 'copy'
 
     input:
-        path input_file
+    path input_file
 
     output:
-        path "UPPER-${input_file}"
+    path "UPPER-${input_file}"
 
     script:
     """
-    cat '$input_file' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
+    cat '${input_file}' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
... (truncated)
hello-nextflow/solutions/4-hello-modules/hello-modules-3.nf
View
@@ -8,15 +8,15 @@ process collectGreetings {
     publishDir 'results', mode: 'copy'
 
     input:
-        path input_files
-        val batch_name
+    path input_files
+    val batch_name
 
     output:
-        path "COLLECTED-${batch_name}-output.txt" , emit: outfile
-        val count_greetings , emit: count
+    path "COLLECTED-${batch_name}-output.txt", emit: outfile
+    val count_greetings, emit: count
 
... (truncated)
hello-nextflow/solutions/4-hello-modules/hello-modules-4.nf
View
@@ -15,8 +15,8 @@ workflow {
 
     // create a channel for inputs from a CSV file
     greeting_ch = channel.fromPath(params.greeting)
-                        .splitCsv()
-                        .map { line -> line[0] }
+        .splitCsv()
+        .map { line -> line[0] }
 
     // emit a greeting
     sayHello(greeting_ch)
@@ -28,5 +28,5 @@ workflow {
     collectGreetings(convertToUpper.out.collect(), params.batch)
 
     // emit a message about the size of the batch
... (truncated)
hello-nextflow/solutions/4-hello-modules/modules/collectGreetings.nf
View
@@ -6,15 +6,15 @@ process collectGreetings {
     publishDir 'results', mode: 'copy'
 
     input:
-        path input_files
-        val batch_name
+    path input_files
+    val batch_name
 
     output:
-        path "COLLECTED-${batch_name}-output.txt" , emit: outfile
-        val count_greetings , emit: count
+    path "COLLECTED-${batch_name}-output.txt", emit: outfile
+    val count_greetings, emit: count
 
... (truncated)
hello-nextflow/solutions/4-hello-modules/modules/convertToUpper.nf
View
@@ -8,13 +8,13 @@ process convertToUpper {
     publishDir 'results', mode: 'copy'
 
     input:
-        path input_file
+    path input_file
 
     output:
-        path "UPPER-${input_file}"
+    path "UPPER-${input_file}"
 
     script:
     """
-    cat '$input_file' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
+    cat '${input_file}' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
... (truncated)
hello-nextflow/solutions/4-hello-modules/modules/sayHello.nf
View
@@ -8,13 +8,13 @@ process sayHello {
     publishDir 'results', mode: 'copy'
 
     input:
-        val greeting
+    val greeting
 
     output:
-        path "${greeting}-output.txt"
+    path "${greeting}-output.txt"
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
... (truncated)
hello-nextflow/solutions/5-hello-containers/modules/cowpy.nf
View
@@ -8,14 +8,14 @@ process cowpy {
     container 'community.wave.seqera.io/library/cowpy:1.1.5--3db457ae1977a273'
 
     input:
-        path input_file
-        val character
+    path input_file
+    val character
 
     output:
-        path "cowpy-${input_file}"
+    path "cowpy-${input_file}"
 
     script:
     """
... (truncated)
hello-nextflow/solutions/6-hello-config/modules/cowpy.nf
View
@@ -9,14 +9,14 @@ process cowpy {
     conda 'conda-forge::cowpy==1.1.5'
 
     input:
-        path input_file
-        val character
+    path input_file
+    val character
 
     output:
-        path "cowpy-${input_file}"
+    path "cowpy-${input_file}"
 
     script:
     """
... (truncated)
hello-nf-core/solutions/composable-hello/hello.nf
View
@@ -14,9 +14,7 @@ include { collectGreetings } from './modules/collectGreetings.nf'
 include { cowpy } from './modules/cowpy.nf'
 
 workflow HELLO {
-
     take:
-    // channel of greetings
     greeting_ch
 
     main:
hello-nf-core/solutions/composable-hello/main.nf
View
@@ -9,12 +9,12 @@ params.greeting = 'greetings.csv'
 workflow {
     // create a channel for inputs from a CSV file
     greeting_ch = channel.fromPath(params.greeting)
-                        .splitCsv()
-                        .map { line -> line[0] }
+        .splitCsv()
+        .map { line -> line[0] }
 
     // call the imported workflow on the channel of greetings
     HELLO(greeting_ch)
 
     // view the outputs emitted by the workflow
-    HELLO.out.view { output -> "Output: $output" }
+    HELLO.out.view { output -> "Output: ${output}" }
... (truncated)
hello-nf-core/solutions/composable-hello/modules/collectGreetings.nf
View
@@ -10,8 +10,8 @@ process collectGreetings {
     val batch_name
 
     output:
-    path "COLLECTED-${batch_name}-output.txt" , emit: outfile
-    val count_greetings , emit: count
+    path "COLLECTED-${batch_name}-output.txt", emit: outfile
+    val count_greetings, emit: count
 
     script:
     count_greetings = input_files.size()
hello-nf-core/solutions/composable-hello/modules/convertToUpper.nf
View
@@ -15,6 +15,6 @@ process convertToUpper {
 
     script:
     """
-    cat '$input_file' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
+    cat '${input_file}' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
     """
 }
hello-nf-core/solutions/composable-hello/modules/cowpy.nf
View
@@ -17,6 +17,6 @@ process cowpy {
 
     script:
     """
-    cat $input_file | cowpy -c "$character" > cowpy-${input_file}
+    cat ${input_file} | cowpy -c "${character}" > cowpy-${input_file}
     """
 }
hello-nf-core/solutions/composable-hello/modules/sayHello.nf
View
@@ -15,6 +15,6 @@ process sayHello {
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
     """
 }
hello-nf-core/solutions/core-hello-part2/conf/base.config
View
@@ -11,13 +11,13 @@
 process {
 
     // TODO nf-core: Check the defaults for all processes
-    cpus   = { 1      * task.attempt }
-    memory = { 6.GB   * task.attempt }
-    time   = { 4.h    * task.attempt }
+    cpus = { 1 * task.attempt }
+    memory = { 6.GB * task.attempt }
+    time = { 4.h * task.attempt }
 
     errorStrategy = { task.exitStatus in ((130..145) + 104 + 175) ? 'retry' : 'finish' }
-    maxRetries    = 1
-    maxErrors     = '-1'
+    maxRetries = 1
... (truncated)
hello-nf-core/solutions/core-hello-part2/conf/modules.config
View
@@ -15,7 +15,6 @@ process {
     publishDir = [
         path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" },
         mode: params.publish_dir_mode,
-        saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
+        saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
     ]
-
 }
hello-nf-core/solutions/core-hello-part2/conf/test.config
View
@@ -14,18 +14,18 @@ process {
     resourceLimits = [
         cpus: 2,
         memory: '4.GB',
-        time: '1.h'
+        time: '1.h',
     ]
 }
 
 params {
-    config_profile_name        = 'Test profile'
+    config_profile_name = 'Test profile'
     config_profile_description = 'Minimal test dataset to check pipeline function'
 
     // Input data
... (truncated)
hello-nf-core/solutions/core-hello-part2/main.nf
View
@@ -13,9 +13,9 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
 
-include { HELLO  } from './workflows/hello'
+include { HELLO } from './workflows/hello'
 include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_hello_pipeline'
-include { PIPELINE_COMPLETION     } from './subworkflows/local/utils_nfcore_hello_pipeline'
+include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_hello_pipeline'
 /*
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     NAMED WORKFLOWS FOR PIPELINE
@@ -26,7 +26,6 @@ include { PIPELINE_COMPLETION     } from './subworkflows/local/utils_nfcore_hell
 // WORKFLOW: Run main analysis pipeline depending on type of input
 //
... (truncated)
hello-nf-core/solutions/core-hello-part2/modules/local/collectGreetings.nf
View
@@ -10,8 +10,8 @@ process collectGreetings {
     val batch_name
 
     output:
-    path "COLLECTED-${batch_name}-output.txt" , emit: outfile
-    val count_greetings , emit: count
+    path "COLLECTED-${batch_name}-output.txt", emit: outfile
+    val count_greetings, emit: count
 
     script:
     count_greetings = input_files.size()
hello-nf-core/solutions/core-hello-part2/modules/local/convertToUpper.nf
View
@@ -15,6 +15,6 @@ process convertToUpper {
 
     script:
     """
-    cat '$input_file' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
+    cat '${input_file}' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
     """
 }
hello-nf-core/solutions/core-hello-part2/modules/local/cowpy.nf
View
@@ -17,6 +17,6 @@ process cowpy {
 
     script:
     """
-    cat $input_file | cowpy -c "$character" > cowpy-${input_file}
+    cat ${input_file} | cowpy -c "${character}" > cowpy-${input_file}
     """
 }
hello-nf-core/solutions/core-hello-part2/modules/local/sayHello.nf
View
@@ -15,6 +15,6 @@ process sayHello {
 
     script:
     """
-    echo '$greeting' > '$greeting-output.txt'
+    echo '${greeting}' > '${greeting}-output.txt'
     """
 }
hello-nf-core/solutions/core-hello-part2/subworkflows/local/utils_nfcore_hello_pipeline/main.nf
View
@@ -8,13 +8,13 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
 
-include { UTILS_NFSCHEMA_PLUGIN     } from '../../nf-core/utils_nfschema_plugin'
-include { paramsSummaryMap          } from 'plugin/nf-schema'
-include { samplesheetToList         } from 'plugin/nf-schema'
-include { paramsHelp                } from 'plugin/nf-schema'
-include { completionSummary         } from '../../nf-core/utils_nfcore_pipeline'
-include { UTILS_NFCORE_PIPELINE     } from '../../nf-core/utils_nfcore_pipeline'
-include { UTILS_NEXTFLOW_PIPELINE   } from '../../nf-core/utils_nextflow_pipeline'
+include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin'
+include { paramsSummaryMap } from 'plugin/nf-schema'
+include { samplesheetToList } from 'plugin/nf-schema'
+include { paramsHelp } from 'plugin/nf-schema'
... (truncated)
hello-nf-core/solutions/core-hello-part2/subworkflows/nf-core/utils_nextflow_pipeline/main.nf
View
@@ -10,9 +10,9 @@
 
 workflow UTILS_NEXTFLOW_PIPELINE {
     take:
-    print_version        // boolean: print version
-    dump_parameters      // boolean: dump parameters
-    outdir               //    path: base directory used to publish pipeline results
+    print_version // boolean: print version
+    dump_parameters // boolean: dump parameters
+    outdir //    path: base directory used to publish pipeline results
     check_conda_channels // boolean: check conda channels
 
     main:
@@ -72,10 +72,10 @@ def getWorkflowVersion() {
 //
... (truncated)
hello-nf-core/solutions/core-hello-part2/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config
View
@@ -1,9 +1,9 @@
 manifest {
-    name            = 'nextflow_workflow'
-    author          = """nf-core"""
-    homePage        = 'https://127.0.0.1'
-    description     = """Dummy pipeline"""
+    name = 'nextflow_workflow'
+    author = """nf-core"""
+    homePage = 'https://127.0.0.1'
+    description = """Dummy pipeline"""
     nextflowVersion = '!>=23.04.0'
-    version         = '9.9.9'
-    doi             = 'https://doi.org/10.5281/zenodo.5070524'
+    version = '9.9.9'
+    doi = 'https://doi.org/10.5281/zenodo.5070524'
... (truncated)
hello-nf-core/solutions/core-hello-part2/subworkflows/nf-core/utils_nfcore_pipeline/main.nf
View
@@ -125,12 +125,12 @@ def paramsSummaryMultiqc(summary_params) {
         }
 
     def yaml_file_text = "id: '${workflow.manifest.name.replace('/', '-')}-summary'\n" as String
-    yaml_file_text     += "description: ' - this information is collected when the pipeline is started.'\n"
-    yaml_file_text     += "section_name: '${workflow.manifest.name} Workflow Summary'\n"
-    yaml_file_text     += "section_href: 'https://github.com/${workflow.manifest.name}'\n"
-    yaml_file_text     += "plot_type: 'html'\n"
-    yaml_file_text     += "data: |\n"
-    yaml_file_text     += "${summary_section}"
+    yaml_file_text += "description: ' - this information is collected when the pipeline is started.'\n"
+    yaml_file_text += "section_name: '${workflow.manifest.name} Workflow Summary'\n"
+    yaml_file_text += "section_href: 'https://github.com/${workflow.manifest.name}'\n"
+    yaml_file_text += "plot_type: 'html'\n"
+    yaml_file_text += "data: |\n"
... (truncated)
hello-nf-core/solutions/core-hello-part2/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config
View
@@ -1,9 +1,9 @@
 manifest {
-    name            = 'nextflow_workflow'
-    author          = """nf-core"""
-    homePage        = 'https://127.0.0.1'
-    description     = """Dummy pipeline"""
-    nextflowVersion  = '!>=23.04.0'
-    version         = '9.9.9'
-    doi             = 'https://doi.org/10.5281/zenodo.5070524'
+    name = 'nextflow_workflow'
+    author = """nf-core"""
+    homePage = 'https://127.0.0.1'
+    description = """Dummy pipeline"""
+    nextflowVersion = '!>=23.04.0'
+    version = '9.9.9'
... (truncated)
hello-nf-core/solutions/core-hello-part2/subworkflows/nf-core/utils_nfschema_plugin/main.nf
View
@@ -2,30 +2,25 @@
 // Subworkflow that uses the nf-schema plugin to validate parameters and render the parameter summary
 //
 
-include { paramsSummaryLog   } from 'plugin/nf-schema'
+include { paramsSummaryLog } from 'plugin/nf-schema'
 include { validateParameters } from 'plugin/nf-schema'
-include { paramsHelp         } from 'plugin/nf-schema'
+include { paramsHelp } from 'plugin/nf-schema'
 
 workflow UTILS_NFSCHEMA_PLUGIN {
-
     take:
-    input_workflow      // workflow: the workflow object used by nf-schema to get metadata from the workflow
-    validate_params     // boolean:  validate the parameters
... (truncated)
hello-nf-core/solutions/core-hello-part2/workflows/hello.nf(truncated)
hello-nf-core/solutions/core-hello-part3/conf/base.config(truncated)
hello-nf-core/solutions/core-hello-part3/conf/modules.config(truncated)
hello-nf-core/solutions/core-hello-part3/conf/test.config(truncated)
hello-nf-core/solutions/core-hello-part3/conf/test_full.config(truncated)
hello-nf-core/solutions/core-hello-part3/main.nf(truncated)
hello-nf-core/solutions/core-hello-part3/modules/local/convertToUpper.nf(truncated)
hello-nf-core/solutions/core-hello-part3/modules/local/cowpy.nf(truncated)
hello-nf-core/solutions/core-hello-part3/modules/local/sayHello.nf(truncated)
hello-nf-core/solutions/core-hello-part3/modules/nf-core/cat/cat/main.nf(truncated)
hello-nf-core/solutions/core-hello-part3/modules/nf-core/cat/cat/tests/nextflow_unzipped_zipped.config(truncated)
hello-nf-core/solutions/core-hello-part3/modules/nf-core/cat/cat/tests/nextflow_zipped_unzipped.config(truncated)
hello-nf-core/solutions/core-hello-part3/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part3/subworkflows/local/utils_nfcore_hello_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part3/subworkflows/nf-core/utils_nextflow_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part3/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part3/subworkflows/nf-core/utils_nfcore_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part3/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part3/subworkflows/nf-core/utils_nfschema_plugin/main.nf(truncated)
hello-nf-core/solutions/core-hello-part3/workflows/hello.nf(truncated)
hello-nf-core/solutions/core-hello-part4/conf/base.config(truncated)
hello-nf-core/solutions/core-hello-part4/conf/modules.config(truncated)
hello-nf-core/solutions/core-hello-part4/conf/test.config(truncated)
hello-nf-core/solutions/core-hello-part4/conf/test_full.config(truncated)
hello-nf-core/solutions/core-hello-part4/main.nf(truncated)
hello-nf-core/solutions/core-hello-part4/modules/local/convertToUpper.nf(truncated)
hello-nf-core/solutions/core-hello-part4/modules/local/cowpy.nf(truncated)
hello-nf-core/solutions/core-hello-part4/modules/local/cowpy/main.nf(truncated)
hello-nf-core/solutions/core-hello-part4/modules/local/sayHello.nf(truncated)
hello-nf-core/solutions/core-hello-part4/modules/nf-core/cat/cat/main.nf(truncated)
hello-nf-core/solutions/core-hello-part4/modules/nf-core/cat/cat/tests/nextflow_unzipped_zipped.config(truncated)
hello-nf-core/solutions/core-hello-part4/modules/nf-core/cat/cat/tests/nextflow_zipped_unzipped.config(truncated)
hello-nf-core/solutions/core-hello-part4/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part4/subworkflows/local/utils_nfcore_hello_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part4/subworkflows/nf-core/utils_nextflow_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part4/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part4/subworkflows/nf-core/utils_nfcore_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part4/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part4/subworkflows/nf-core/utils_nfschema_plugin/main.nf(truncated)
hello-nf-core/solutions/core-hello-part4/workflows/hello.nf(truncated)
hello-nf-core/solutions/core-hello-part5/conf/base.config(truncated)
hello-nf-core/solutions/core-hello-part5/conf/modules.config(truncated)
hello-nf-core/solutions/core-hello-part5/conf/test.config(truncated)
hello-nf-core/solutions/core-hello-part5/conf/test_full.config(truncated)
hello-nf-core/solutions/core-hello-part5/main.nf(truncated)
hello-nf-core/solutions/core-hello-part5/modules/local/convertToUpper.nf(truncated)
hello-nf-core/solutions/core-hello-part5/modules/local/cowpy.nf(truncated)
hello-nf-core/solutions/core-hello-part5/modules/local/cowpy/main.nf(truncated)
hello-nf-core/solutions/core-hello-part5/modules/local/sayHello.nf(truncated)
hello-nf-core/solutions/core-hello-part5/modules/nf-core/cat/cat/main.nf(truncated)
hello-nf-core/solutions/core-hello-part5/modules/nf-core/cat/cat/tests/nextflow_unzipped_zipped.config(truncated)
hello-nf-core/solutions/core-hello-part5/modules/nf-core/cat/cat/tests/nextflow_zipped_unzipped.config(truncated)
hello-nf-core/solutions/core-hello-part5/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part5/subworkflows/local/utils_nfcore_hello_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part5/subworkflows/nf-core/utils_nextflow_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part5/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part5/subworkflows/nf-core/utils_nfcore_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-part5/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-part5/subworkflows/nf-core/utils_nfschema_plugin/main.nf(truncated)
hello-nf-core/solutions/core-hello-part5/workflows/hello.nf(truncated)
hello-nf-core/solutions/core-hello-start/conf/base.config(truncated)
hello-nf-core/solutions/core-hello-start/conf/modules.config(truncated)
hello-nf-core/solutions/core-hello-start/conf/test.config(truncated)
hello-nf-core/solutions/core-hello-start/conf/test_full.config(truncated)
hello-nf-core/solutions/core-hello-start/main.nf(truncated)
hello-nf-core/solutions/core-hello-start/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-start/subworkflows/local/utils_nfcore_hello_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-start/subworkflows/nf-core/utils_nextflow_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-start/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-start/subworkflows/nf-core/utils_nfcore_pipeline/main.nf(truncated)
hello-nf-core/solutions/core-hello-start/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config(truncated)
hello-nf-core/solutions/core-hello-start/subworkflows/nf-core/utils_nfschema_plugin/main.nf(truncated)
hello-nf-core/solutions/core-hello-start/workflows/hello.nf(truncated)
side-quests/solutions/essential_scripting_patterns/collect.nf(truncated)
side-quests/solutions/essential_scripting_patterns/main.nf(truncated)
side-quests/solutions/essential_scripting_patterns/modules/fastp.nf(truncated)
side-quests/solutions/essential_scripting_patterns/modules/trimgalore.nf(truncated)
side-quests/solutions/metadata/1/main.nf(truncated)
side-quests/solutions/metadata/2/main.nf(truncated)
side-quests/solutions/metadata/3.2/main.nf(truncated)
side-quests/solutions/metadata/3.2/modules/cowpy.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/conf/base.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/conf/modules.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/conf/test.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/conf/test_full.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/modules/local/fastqe/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/modules/nf-core/multiqc/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/modules/nf-core/multiqc/tests/nextflow.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/modules/nf-core/seqtk/trim/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/nextflow.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/subworkflows/local/utils_nfcore_myfirstpipeline_pipeline/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/subworkflows/nf-core/utils_nextflow_pipeline/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/subworkflows/nf-core/utils_nextflow_pipeline/tests/nextflow.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/subworkflows/nf-core/utils_nfcore_pipeline/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/subworkflows/nf-core/utils_nfcore_pipeline/tests/nextflow.config(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/subworkflows/nf-core/utils_nfschema_plugin/main.nf(truncated)
side-quests/solutions/nf-core/myorg-myfirstpipeline/workflows/myfirstpipeline.nf(truncated)
side-quests/solutions/nf-test/tests/nextflow.config(truncated)
side-quests/solutions/splitting_and_grouping/main.nf(truncated)
side-quests/solutions/workflow_management_fundamentals/nextflow/main.nf(truncated)
side-quests/solutions/workflow_management_fundamentals/nextflow/modules/fastp.nf(truncated)
side-quests/solutions/workflow_management_fundamentals/nextflow/modules/fastqc.nf(truncated)

pinin4fjords and others added 22 commits January 12, 2026 15:45
- Replace placeholder FASTQ files with valid 3-read test data
- Convert FASTQC module to generate mock HTML/ZIP reports
- Convert FASTP module to pass-through reads with mock QC reports
- Convert SPADES module to generate mock assembly contigs
- Convert QUAST module to generate mock quality reports
- Update nextflow.config to disable Docker by default for mocks
- Add Docker profile for running with real bioinformatics containers

The tutorial now executes end-to-end without requiring real
bioinformatics tools, while still demonstrating all Nextflow
workflow management concepts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Major restructure to match standard tutorial format:

- Add starter files (main.nf, fastqc.nf, nextflow.config, process_one.sh)
- Rewrite documentation with Before/After code blocks
- Remove "Your Task/Solution" exercise format
- Add progressive hands-on sections:
  1. Bash script problem demonstration
  2. Nextflow introduction with starter workflow
  3. Add FASTP, SPADES, QUAST incrementally
  4. Configuration profiles
- All code is executable with mock bioinformatics processes
- Solutions directory contains completed versions

Tested walkthrough end-to-end with verified caching and parallelization.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Focus on persuading users WHY workflow management matters, not teaching
Nextflow syntax. Tutorial now covers six key problems:

1. Sequential Processing → Automatic parallelization
2. No Resume After Failure → Built-in caching
3. "Works on My Machine" → Per-process containers
4. Scaling Requires Rewriting → Declarative scaling
5. No Audit Trail → Automatic provenance
6. Tied to One Environment → Configuration profiles

Changes:
- Reorganize docs around problem-solution pairs
- Create bash_pipeline.sh that demonstrates limitations
- Create nextflow_pipeline/ with complete workflow
- Add container directives to show software isolation
- Add profiles for laptop/slurm/aws/gcp execution
- Remove hands-on "build from scratch" approach
- Position Nextflow as example of workflow management tools

Tested both pipelines:
- Bash: ~34 seconds sequential
- Nextflow: ~12 seconds parallel, all 12 tasks cache on resume

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Think about it" sections before each solution to prompt critical thinking
- Add Section 3.6 on Effortless Collaboration (sharing workflows, nf-core)
- Inspired by Seqera Academy teaching approaches

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace mock bacterial genome assembly with real RNA-seq workflow
- Use nf-core test-datasets (GSE110004 yeast study) for real data
- Workflow: FastQC → fastp → Salmon → MultiQC
- Bash script runs actual tools (requires conda installation)
- Nextflow runs same tools in containers (no installation needed)
- Add installation instructions for bash script prerequisites
- Update documentation to reflect RNA-seq scenario
- Add reflection questions and collaboration sections

Co-Authored-By: Claude <noreply@anthropic.com>
The key difference is not bash=conda vs nextflow=docker, but rather:
- Bash: YOU manage environments (install, activate, document, troubleshoot)
- Nextflow: WORKFLOW manages environments declaratively (just run it)

Co-Authored-By: Claude <noreply@anthropic.com>
Testing identified two critical bugs that are now fixed:
- Bash parallelization: tail | while creates subshell preventing wait
  from tracking background jobs. Fixed with process substitution.
- Salmon index: queue channel consumed after first sample. Fixed with
  .first() to convert to value channel that broadcasts.

Added new content emphasizing key workflow management benefits:
- Separation of concerns (process definitions vs workflow logic)
- Automatic task retries with dynamic resource allocation
- Cluster/cloud execution without code changes
- Transparent remote file handling (URLs as local files)
- Per-process resource management (cpus, memory, maxForks)

Restructured directory layout:
- bash/ for learner bash script progression
- nextflow/ for learner Nextflow pipeline
- solutions/ for reference implementations

Simplified solution to match tutorial content (removed MultiQC).
Updated all summary tables throughout documentation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Restructured to match training conventions:
- ## 1. Building a Bash Pipeline (Part 1 container)
  - ### 1.1. through ### 1.10. for sections
- ## 2. Building a Nextflow Pipeline (Part 2 container)
  - ### 2.1. through ### 2.8. for sections
- Sub-subsections converted to #### (unnumbered)
- Fixed code block comment that triggered false positive

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Convert documentation to use tabbed Before/After blocks for each change
- Create starter files with TODO placeholders (bash) and ??? (Nextflow)
- Learners only write code for learning outcomes (tool commands, I/O, wiring)
- Provide all boilerplate (script structure, process headers, loop structure)
- Fix hl_lines attributes to correctly highlight changed lines
- Same granularity for both bash and Nextflow sections

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The solution files use relative paths (../data/samples.csv) which
require a data directory to exist. This symlink points to the shared
data directory so solutions can be run without extra parameters.

Tested with Docker:
- Nextflow solution: All 10 tasks complete (UNTAR, FASTQC, FASTP, SALMON_QUANT)
- Bash starters: Valid syntax verified
- Nextflow starters: Expected syntax errors from ??? placeholders

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After tab now appears first, consistent with other training materials.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Explain what learners are doing and why before each code block
- Add "Understanding the Starter Script" section for bash part
- Explain val() vs path(), emit:, and .first() in Nextflow sections
- Connect each step to learning objectives
- Clarify the two-input pattern for Salmon (per-sample + shared reference)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bash sections:
- Emphasize limitations without forward references to Nextflow
- Stress reproducibility issues, resource limits, cluster rewrites
- Let the problems speak for themselves

Nextflow sections:
- Explicitly contrast with bash pain points
- "Remember in bash...? Here's how Nextflow handles it"
- Connect each feature to a specific bash limitation solved

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 7 production-quality standards upfront as bullet points
- Clarify this applies to all scripting approaches, not just bash
- Emphasize software management is about per-task isolation, not
  just version locking (conda installs everything in one env)
- Add note explaining bash is used as example but issues apply to
  Python, R, etc.
- Update summaries with scorecard bullets referencing standards
- Change "Contrast with bash" tips to "Contrast with scripts"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Scripts hit resource limits on single machine and require complete
rewrite for cluster/cloud. Nextflow manages local resources and
scales to distributed infrastructure with config change.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Direct readers to Hello Nextflow for thorough introduction.
This side quest focuses on illustrating workflow management
benefits rather than teaching Nextflow in depth.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Tie back to opening question about why learn a framework
- Summarize key insight: scripts mix science with infrastructure
- Point to Hello Nextflow for proper learning
- Link to docs, nf-core, and Seqera Platform for further exploration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Skills transfer between projects/organizations when using common
frameworks. New team members contribute immediately instead of
learning homegrown solutions. Community shares patterns and tools.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Frame as workflow managers generally being established tools with
communities and transferable concepts, not assuming everyone uses
the same specific framework.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@pinin4fjords pinin4fjords marked this pull request as ready for review January 13, 2026 10:04
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@pinin4fjords pinin4fjords changed the title [WIP] Add Workflow Management Fundamentals side quest Add Workflow Management Fundamentals side quest Jan 13, 2026
Copy link
Collaborator

@adamrtalbot adamrtalbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great start! I have some comments:

  • reduce the gushing over workflows a bit, show don't tell
  • reduce the rate of hyphens.
  • we shouldn't over explain how a Nextflow process works. Just highlight the features (inputs, outputs, script, software packaging). If a user wants to learn how to use Nextflow, they should move to hello-nextflow afterwards.

- **Efficient parallelization** - Independent tasks run simultaneously, so analysis completes in hours, not days.
- **Resource awareness** - Respects memory and CPU limits. No crashed jobs or killed processes.
- **Failure recovery** - Can resume from where it stopped. A single failure doesn't waste hours of completed work.
- **Portability** - Runs on laptop, cluster, or cloud with the same code.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Polyglot?


#### 1.3.4. Add Salmon Index Download

Salmon needs a pre-built index of the reference transcriptome. We'll download a pre-built index (to save time) only if it doesn't already exist. This avoids re-downloading for every sample.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's possibly a lesson on conditional logic here, which is easier in a workflow language.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, ish. It may be a trickier conceptually in Nextflow, but it's more robust (detecting the directory vs the object existing).

Changes:
- Fix LLM-cliche phrasing ("The question is how can we achieve...")
- Reformat tutorial overview table with Software column
- Add note about conditional logic fragility in scripts vs workflows
- Tone down gushing language throughout ("There has to be a better way" etc)
- Fix container accuracy - Nextflow supports multiple software packaging tools
- Streamline FASTQC process explanation - show complete process first
- Simplify container tip text
- Use val(id) instead of val(meta) throughout - simpler for intro tutorial
- Tone down LLM language patterns (removed "Remember...?" callbacks, "magic", etc)
- Add MultiQC aggregation section to BOTH bash and Nextflow parts to show
  workflow benefits for complex pipelines with multiple outputs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@pinin4fjords
Copy link
Collaborator Author

Changes addressing review feedback

Adam's specific comments addressed:

  • Line 29: Fixed LLM-cliche phrasing → "The question is how can we achieve this in one pipeline?"
  • Line 46: Reformatted table with Software column
  • Line 284: Added note about conditional logic fragility (directory checks vs actual task success)
  • Line 585: Toned down "There has to be a better way" → "This is where workflow managers come in."
  • Line 618: Fixed container accuracy - now mentions Nextflow supports multiple software packaging tools, not just containers
  • Line 666: Streamlined FASTQC process explanation - shows complete process first, then brief explanation
  • Line 743: Simplified container tip text
  • Line 898: Changed val(meta) to val(id) throughout - simpler for an intro tutorial

Additional changes per feedback:

  • Toned down LLM language throughout - replaced "Remember...?" rhetorical callbacks with "In Part 1..." factual references, changed "The Magic of Resume" to "Resume and Caching", removed dramatic one-liners
  • Added MultiQC aggregation sections to both Part 1 (bash) and Part 2 (Nextflow) to better demonstrate workflow benefits for complex pipelines - this addresses the feedback that it "doesn't quite hit home the benefit of workflows for complex pipelines"

Unclear comments (left as-is for clarification):

  • Line 25 "Polyglot?" - "Portability" seems correct for describing cross-platform execution
  • Line 614 empty suggestion - This was the "#### No Tool Installation Needed" header, unclear what was intended

pinin4fjords and others added 2 commits January 14, 2026 11:00
Removed section on tool installation requirements in Nextflow.
- Add "Software Management" header for orphaned section
- Tone down exclamations ("It worked!" -> "This works", "Much faster!" -> "Faster, because...")
- Remove LLM phrase "worth mentioning"
- Strip trailing dash phrases that added redundant emphasis
- Tighten prose throughout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants