Your project's files

A project from amber init is two things at once. It is a library: packages of Smalltalk that another project can install. And it is an application: a page, and the machinery that builds the page and serves it. The files sort into these two parts, and a third: what the build generates. The example is the Hello Amber project from the install page.

The library part

Three files make the library. They are what a published Amber library ships, and nothing else is needed.

src/ holds the packages. The sample has three: HelloAmber, HelloAmber-Tests and HelloAmber-Backend. Each package is a .st file and a .js file beside it. The .st file is the source. It is in the chunk format of Smalltalk, with ! between the chunks. The .js file is compiled from it, and the page loads the .js. When you commit a package in Helios, the server writes both files. grunt default compiles every .js from its .st again.

The first lines of src/HelloAmber.st are these:

Smalltalk createPackage: 'HelloAmber'!
(Smalltalk packageAt: 'HelloAmber' ifAbsent: [ self error: 'Package not created: HelloAmber' ]) imports: {'amber/jquery/Web-JQuery'. 'amber/web/Web'. 'silk/Silk'}!

The imports name the modules the package needs. The sample imports Web, Silk, and the jQuery extension of Web. The compiled HelloAmber.js requests them from the loader, and Amber waits for them before it counts the package as ready. An import can also bind a module to a name, as 'moment' -> 'moment'; the JavaScript page shows that.

local.amd.json gives the project its namespace:

{
  "paths": {
    "amber-helloamber": "src"
  }
}

A module of this project is addressed by that namespace: amber-helloamber/HelloAmber is src/HelloAmber.js. Every Amber library has such a file. Silk’s maps silk to its src, so silk/Silk is Silk’s package. A project that installs your library reads your file and knows where your packages are.

package.json is the npm manifest. Its dependencies are the Amber libraries the sample uses. @ambers/lang is Amber itself. @ambers/contrib-web comes with @ambers/contrib-jquery, and @ambers/silk with @ambers/domite. Its devDependencies are what development needs and the deployed application does not. There are @ambers/sdk with the compiler and the grunt tasks, @ambers/helios, the legacy IDE in @ambers/contrib-legacy, and the starter dialog. The rest are grunt and its plugins, requirejs and terser. The scripts are npm run init, which installs and builds, npm run reset, which deletes node_modules first, and npm test.

README.md and LICENSE-MIT are yours to edit. The README was written for a library, and says which paragraph to delete when the project is an application.

The machinery

index.html is the page of the application. Its head loads one script, the.js. Its body holds the sample’s buttons between two comments, EXAMPLE APP START and EXAMPLE APP END. The script at the end of the body starts everything. It requires the module app and waits for Amber to initialize. Then it shows the IDE starter dialog, if its module is present, and calls amber.globals.HelloAmber._start(). That is the class method start of HelloAmber. Amber names a compiled selector with an underscore before it, and an underscore in place of each colon.

The initialize call sets one option, transport.defaultAmdNamespace, to amber-helloamber. It is the namespace Helios gives every package you create in it.

deploy.js, testing.js, devel.js, lambda.js are four lists of packages. Each is a module that lists the modules to load:

File Loads
deploy.js Amber’s amber/deploy, and amber-helloamber/HelloAmber. This is the application.
lambda.js amber/deploy, and amber-helloamber/HelloAmber-Backend. This is the backend.
testing.js Both of those, amber/core/SUnit, and amber-helloamber/HelloAmber-Tests.
devel.js testing.js, Amber’s amber/devel with the compiler and the reflection, and the legacy IDE with its examples.

When you add a package to the project, you add its module to the right list. Each file has a comment that marks where. A package the application needs goes into deploy.js. A package only the tests need goes into testing.js.

Gruntfile.js defines the build. It has five tasks. default compiles the packages. devel builds the.js for development. test runs the tests under Node.js. deploy builds the.js for release, and deploy:lambda builds the backend. The amberc section lists the .st files to compile, in dependency order, and the libraries to load before compiling them. The build page goes through the tasks.

lambda/index.js is a handler for AWS Lambda. It loads lambda/the.js and maps two exports, status and echo, to two methods of HelloAmberBackend. A project with no backend deletes it, with lambda.js and the backend package.

parts.html and uninstall.html are two notes from the generator. The first says which files belong to which part. The second says what to remove when you start your own work. Both can be deleted.

.gitignore lists node_modules and the generated files below.

What the build generates

config.js is the loader configuration. The amdconfig task collects every .amd.json file in the project into one require.config call. That is the project’s own local.amd.json, and the files of every package under node_modules. The result maps each namespace to a directory. amber is Amber’s kernel, amber/core is Amber’s packages, and amber-helloamber is src, with silk, helios and jquery beside them. Helios needs this file. The deployed application does not. Every grunt task regenerates it first, so it is never edited by hand.

the.js is the one script the page loads. The requirejs optimizer builds it. After grunt devel it holds the loader, the configuration and the entry point. Every package is loaded from its own file, so that Helios sees each file as it is. After grunt deploy it holds everything the application needs, minified by terser. Then index.html and the.js are the whole application.

lambda/the.js is the same for the backend. test_runner.js is built by grunt test and deleted when the tests have run.

From the sample to your own work

The sample shows two ways to work with the page, so that you can choose. Silk, with Domite under it, is one. Web, with jQuery through contrib-jquery, is the other. Keep one. Remove the other from the imports of your package, from package.json, and from the libraries list in Gruntfile.js. Then run npm run reset, so that node_modules matches package.json again.

In index.html, remove what lies between the two EXAMPLE APP comments and put your own page there. Keep the script at the end: it starts your application.