Skip to main content

Overview

Utopia Fleet Builder uses Grunt as its task runner to automate the build process. The build system:
  • Compiles AngularJS templates into JavaScript
  • Minifies and concatenates JavaScript files
  • Minifies and combines CSS stylesheets
  • Generates game data from source modules
  • Copies static assets to the build directory
All build configuration is defined in gruntfile.js at the project root.

Build Architecture

Grunt Tasks

Main Build Tasks

The default task runs a complete build of the application.
grunt
# or
npm start
Executes in order:
  1. build-js - JavaScript compilation
  2. build-css - CSS compilation
  3. build-index - HTML files
  4. build-data - Game data generation
  5. copy - Static assets
  6. clean:templates - Cleanup temporary files
Defined in gruntfile.js:
grunt.registerTask('default', [
  "build-js",
  "build-css",
  "build-index",
  "build-data",
  "copy",
  "clean:templates"
]);
Compiles Angular templates and JavaScript into a single minified file.
grunt build-js
Steps:
  1. ngtemplates - Compiles HTML templates to staw-utopia/utopia-templates.js
  2. uglify - Minifies and concatenates:
    • All JS files from src/js/*.js
    • All JS files from src/js/common/**/*.js
    • Generated templates file
Output: staw-utopia/js/utopia.min.js (with source map)
Source maps are generated for debugging minified code.
Minifies and combines CSS stylesheets.
grunt build-css
Steps:
  1. cssmin - Minifies CSS files:
    • src/css/*.css
    • src/css/common/*.css
    • Excludes utopia-print.css
  2. copy:css - Copies print stylesheet separately
Output:
  • staw-utopia/css/utopia.min.css (main styles)
  • staw-utopia/css/utopia-print.css (print styles)
Copies HTML files to the build directory.
grunt build-index
Copies:
  • src/*.html
  • src/staw-utopia/*.html
Output: staw-utopia/*.html
Generates the game data JSON file from source modules.
grunt build-data
Process:
  1. Executes npm run data via Node child process
  2. Runs ESLint on data files
  3. Executes src/data/index.js to generate JSON
Output: staw-utopia/data/data.json
If data generation fails, the build stops with an error.
Monitors source files and automatically rebuilds on changes.
grunt watch
# or
npm run watch
Watches:
  • Gruntfile.js → Reloads Grunt configuration
  • src/js/*.js, src/js/common/**/*.jsbuild-js
  • src/templates/*.html, src/templates/common/*.htmlbuild-js
  • src/css/**.css, src/css/common/*.cssbuild-css
  • src/*.html, src/staw-utopia/*.htmlbuild-index
  • src/data/*build-data

Grunt Plugin Configuration

ngtemplates (Angular Templates)

Compiles HTML templates into an AngularJS module.
ngtemplates: {
  utopia: {
    cwd: "src/templates",
    src: ["*.html", "common/*.html"],
    dest: "staw-utopia/utopia-templates.js",
    options: {
      url: function(url) {
        // Extracts just the filename, removing directory path
        var i = url.lastIndexOf("/");
        if (i >= 0 && i < url.length)
          url = url.substring(i+1);
        return url;
      }
    }
  }
}
Template URLs are simplified to just filenames, making them easier to reference in Angular code.

uglify (JavaScript Minification)

Minifies JavaScript with source map support.
uglify: {
  js: {
    files: {
      "staw-utopia/js/utopia.min.js": [
        "src/js/*.js",
        "src/js/common/**/*.js",
        "<%= ngtemplates.utopia.dest %>"
      ]
    },
    options: {
      sourceMap: {
        includeSources: true
      }
    }
  }
}
Features:
  • Concatenates all JS files in order
  • Includes compiled templates
  • Generates source maps for debugging
  • Includes original source code in map

cssmin (CSS Minification)

Minifies and combines CSS files.
cssmin: {
  css: {
    files: {
      "staw-utopia/css/utopia.min.css": [
        "src/css/*.css",
        "src/css/common/*.css",
        "!src/css/utopia-print.css"
      ]
    }
  }
}
Print styles are excluded from the main bundle and copied separately to allow conditional loading.

copy (Asset Copying)

Copies static assets to the build directory.
copy: {
  misc: {
    expand: true,
    cwd: "src",
    src: ["js/lib/*", "fonts/*", "img/**/*", "assets/**"],
    dest: "staw-utopia/"
  },
  css: {
    expand: true,
    cwd: "src",
    src: ["css/utopia-print.css"],
    dest: "staw-utopia/"
  },
  csslib: {
    expand: true,
    cwd: "src/css/lib",
    src: ["*.css"],
    dest: "staw-utopia/css/"
  },
  index: {
    expand: true,
    cwd: "src",
    src: ["*.html", "staw-utopia/*.html"],
    dest: "staw-utopia/"
  },
  powertip: {
    expand: true,
    cwd: "node_modules/jquery-powertip/dist",
    src: ["jquery.powertip.min.js"],
    dest: "staw-utopia/js/lib/"
  },
  powertip_css: {
    expand: true,
    cwd: "node_modules/jquery-powertip/dist/css",
    src: ["jquery.powertip.min.css"],
    dest: "staw-utopia/css/"
  }
}
Copies:
  • Third-party JavaScript libraries
  • Font files
  • Images and icons
  • PDF assets
  • jQuery PowerTip plugin
  • CSS libraries

clean (Cleanup)

Removes temporary or generated files.
clean: {
  build: ["staw-utopia/*"],           // Full clean
  templates: ["staw-utopia/utopia-templates.js"]  // Cleanup after build
}
The clean:build task is commented out in the default task to avoid full rebuilds. Use manually if needed.

Build Outputs

After a successful build, the staw-utopia/ directory contains:
staw-utopia/
├── index.html                    # Main application entry
├── staw-utopia/
│   └── index.html                # Alternate entry point
├── js/
│   ├── utopia.min.js             # Minified application JS
│   ├── utopia.min.js.map         # Source map for debugging
│   └── lib/
│       ├── angular.min.js        # AngularJS library
│       ├── jquery.min.js         # jQuery library
│       └── jquery.powertip.min.js # Tooltip library
├── css/
│   ├── utopia.min.css            # Minified application CSS
│   ├── utopia-print.css          # Print-specific styles
│   ├── jquery.powertip.min.css   # Tooltip styles
│   └── *.css                     # Other CSS libraries
├── data/
│   └── data.json                 # Complete game data
├── fonts/
│   └── ...                       # Font files
├── img/
│   ├── ships/
│   ├── stuff/
│   └── ...                       # Image assets
└── assets/
    └── pdf/                      # PDF resources

Build Performance

Full Build

~10-20 secondsRuns all tasks from scratch

Incremental (Watch)

~1-3 secondsOnly rebuilds changed files

Optimization Tips

1

Use Watch Mode

Keep grunt watch running during development to avoid full rebuilds:
npm run watch
2

Build Specific Tasks

If you only changed CSS, run just the CSS task:
grunt build-css
3

Skip Source Maps in Production

For production builds, consider disabling source maps by modifying the uglify options.

Troubleshooting

Problem: Grunt can’t find a registered task.Solution: Ensure the plugin is loaded:
grunt.loadNpmTasks('grunt-plugin-name');
Problem: Minification breaks the application.Solution:
  • Check for missing semicolons in source
  • Use the source map for debugging
  • Temporarily disable uglify to isolate the issue
Problem: Angular template changes don’t appear.Solution:
  1. Verify watch is monitoring src/templates/*.html
  2. Run grunt build-js manually
  3. Hard refresh browser (clear template cache)
Problem: build-data task errors.Solution:
  • Check ESLint output: npm run lint-data
  • Fix syntax errors in data files
  • Verify all data modules export valid arrays/objects

Customizing the Build

To modify the build process:
  1. Edit gruntfile.js at the project root
  2. Add new tasks or modify existing configurations
  3. Load additional plugins with grunt.loadNpmTasks()
  4. Register custom tasks with grunt.registerTask()
Test changes thoroughly before committing modifications to gruntfile.js. Build issues can break the entire development workflow.

Next Steps

Data Structure

Learn how game data is organized

Contributing

Guidelines for submitting changes

Build docs developers (and LLMs) love