# Publish and use a module

## Publish the package

A module is a Dart package, so you publish it on pub.dev like any other, with `dart pub publish`. Before you publish:

- bundle the bricks again and commit the bundles in `lib/bundles/`, which the package needs;
- run the tests with the contract harness, `ModulePackage` and `roleClassNameProblems` (see [Test a module](https://doc.saymyframe.com/extending/testing.md));
- depend on the version of `smf_contracts` that the module is written for, such as `smf_contracts: ^0.8.0`;
- publish the packages that your package depends on first, such as the package of a module in your `dependsOn` or of a role of your own, since a package on pub.dev can depend only on packages that are on pub.dev.

## A command of your own

`smf` offers the modules in its own list. A command of your own adds your modules to that list. Create a small package that depends on `smf_flutter_cli` and on your module:

```yaml title="pubspec.yaml"
name: my_smf
description: smf with the counter feature.
version: 0.1.0
publish_to: none

environment:
  sdk: ^3.12.0

executables:
  my_smf:

dependencies:
  smf_counter: ^0.1.0
  smf_flutter_cli: ^0.8.0
```

```dart title="bin/my_smf.dart"
import 'dart:io';

import 'package:smf_counter/smf_counter.dart';
import 'package:smf_flutter_cli/smf_flutter_cli.dart';

Future<void> main(List<String> arguments) async {
  final code = await runCli(
    arguments,
    modules: const [...smfModules, CounterModule()],
  );
  await Future.wait<void>([stdout.flush(), stderr.flush()]);
  exit(code);
}
```

`runCli` is the command line of `smf`. It takes the arguments, runs the pipeline on this machine with the modules you give it, and returns the exit code. `smfModules` is the list of the built-in modules, in the order in which the questions of `smf create` offer them, and your modules come after them. Run the command from the package, or activate it globally like any Dart command-line tool:

```bash
dart run bin/my_smf.dart create my_app -m home,counter,bottom_tabs,bloc
```

The command has every option and question of `smf create`, and its help calls it `smf`. With `runCli(..., banner: false)`, it leaves out the note with links to the SMF community that follows a created app.

The list of modules must form a valid registry, which the command checks before it parses the command line:

- a module of the list provides the app entry, as `flutter_core` does;
- the ids of modules and roles are unique, and every module in a `dependsOn` is in the list;
- every key of a module's variants is a module of the list that provides the role.

A command with a registry that breaks these rules prints the problems and exits with code 70.

## Propose it for SMF

A module that many apps need, or a new provider of a built-in role, can become part of SMF itself. Open an issue first to agree on what the module does and how it fits the roles. See [Contributing](https://doc.saymyframe.com/contributing.md).
