# Project Structure
Litexa provides you with three different strategies to organize your code, each of which has a specific philosophy behind it:
- Inlined ... ideal for smaller projects with limited dependencies
- Separate ... ideal for medium-sized, modular projects
- Bundled ... ideal for compressing large, multi-layered projects
In order to help you select the strategy that's right for you, we'll approach the problem pragmatically by looking at it through the lens of an Alexa skill. Assume you've been tasked with building the following trivia skill:
Gameplay
- Player launches the game, upon which Alexa reads the rules.
- The game consists of 3 rounds of at most 10 clues each.
- In a round, each consecutive clue becomes increasingly easier.
- The more clues it takes before the player answers correctly, the fewer points the player receives. For instance:
- correct answer after first clue: 10 points
- correct answer after tenth clue: 1 point
- After all 3 rounds, Alexa announces the player's score and exits.
Below we'll take a look at each strategy in turn, and discuss when it might be meaningful for you to use that strategy for the above skill's development.
# Inlined
Let's assume you want to quickly prototype and iterate your trivia skill to answer questions such as:
- Is the game's concept viable?
- What can I do to make the game fun?
- What wording sounds good for Alexa's prompts?
- How long should Alexa wait between clues?
- Should there be silence or audio between clues?
This would be a scenario where choosing the inlined project structure is meaningful.
Use Inlined when:
- rapid prototyping and iteration are desired
- few or no external dependencies are required
- there is no need to
import
/require
self-authored files - project size is small
# Generation
The decision to pick a project structure happens when you litexa generate
a project. There are two ways to generate
a project with an inlined structure.
You can use generation flags like this:
litexa generate quiz-trivia-inlined --bundling-strategy none
Defaults
If you use flags, you will not be prompted about which language to use for your configuration files (i.e.
litexa.config.*
andskill.*
in project root) or your source code: They will default to JavaScript. To specify these options you can pass them as flag options to thegenerate
command.Your options are as follows:
-c, --config-language [configLanguage] language of the generated configuration file, can be javascript, json, typescript, or coffee -s, --source-language [sourceLanguage] language of the generated source code, can be javascript, typescript, or coffee -b, --bundling-strategy [bundlingStrategy] the structure of the code layout as it pertains to litexa, can be webpack, npm-link, or none
To see your generation options you can run
litexa generate --help
.or, if you aren't using flags:
litexa generate quiz-trivia-inlined
and select the following answer when prompted:
? How would you like to organize your code? Inlined in litexa
NOTE
If you prefer, litexa init
is available as an equivalent to litexa generate
.
# Structure
An inlined project would look something like this:
.
├── README.md
├── artifacts.json
├── litexa
│ ├── assets
│ │ ├── icon-108.png
│ │ └── icon-512.png
│ ├── main.litexa
│ ├── main.test.litexa
│ └── utils.js
├── node_modules
├── package-lock.json
├── package.json
├── litexa.config.js
└── skill.js
Here's a full breakdown of all the files and directories you could have in an inlined Litexa project:
litexa.config.(json|js|ts|coffee)
file is the Litexa configuration. A Litexa project is any directory with a valid Litexa configuration file.skill.(json|js|ts|coffee)
file contains a subset of the information found in an Alexa skill manifest (opens new window). Placeholders within (e.g. skill summary and description) should be replaced according to the skill's usage.artifacts.json
file captures information about the project, such as the skill ID for each deployment or the ARN of lambdas (and the Git commit hash, when using Git). Please refer to the artifacts.json guidelines for information on sharing this file.tsconfig.json
andtslint.json
files exist if you use TypeScript to configure your project. They contain your project configuration's compilation and linting settings.package.json
is a standard npm file and is necessary when you have npm packages you would like to depend on but that will not be shipped with the skill (such as build tools and compile-time extensions).package-lock.json
is the standard npm lock file that is responsible for deterministic installation of your project dependencies.node_modules
contains all of the packages you installed with npm as specified in the package.json file. These packages will NOT be deployed with your skill.README.md
file contains information about your generated project's structure.litexa
directory contains your assets, Litexa files, and skill logic:*.litexa
files are the Litexa language files.*.(js|ts|coffee)
files are code files. Any functions or variables you define here are visible within the states defined in your.litexa
files.assets
contains any images, videos and sounds you'd like to deploy with your project.languages
contains a directory per additional language you'd like to support, beyond your default language (see Localization for more details).package.json
is a standard npm file and is necessary when you have npm packages you would like to depend on at runtime.package-lock.json
is the standard npm lock file that is responsible for deterministic installation of your project dependencies.node_modules
contains all of the packages you installed with npm as specified in the package.json file. These packages WILL be deployed along with your handler.tsconfig.json
andtslint.json
files will exist if you chose TypeScript as the source code language for your project. They will contain your project code's compilation and linting settings.
# Up and Running
The generated project should now be ready for use as-is (unless you're using TypeScript - see additional steps
below), meaning you should now be able to run litexa test
and litexa deploy
!
Additional TypeScript Setup
- If you chose TypeScript as the language for your configuration files you need to run the following commands from your project's root directory.
- If you chose TypeScript as the language for your source code files, you need to run the following
commands from within your project's
litexa
directory.
npm install
npm run compile
Note, that the following utility scripts will also compile your configuration files, when run from your project's
root directory (assuming you've run npm install
):
npm run test
npm run deploy
# Using external packages
If you want to add external runtime dependencies that you want to ship with your Litexa project, you can do so using
npm. Inside your project's litexa
directory, run:
npm init
Answer the prompts which will create a package.json
file in your litexa
directory. Then, save any runtime
dependencies you require, by running:
npm install --save [your dependency]
You can then require the external packages from any of your inline code files and use them in the Litexa scope.
On deployment, the entire contents of litexa/node_modules
will be deployed alongside your skill handler.
To add tools for use during the development of your skill, you can also create a package.json
file in your project's
root directory and install dependent modules in the same way. These should not be runtime dependencies, since they
won't deploy with your code.
Extensions
Some Litexa extension packages with runtime functionality are designed to be installed at the project's root directory since their runtime code will be inlined in the handler.
When installing a Litexa extension, consult its README for installation instructions.
Require/Import
Only require
/import
packages that are added as dependencies in litexa/package.json
. Do not use an inlined
project structure if you need to require
/import
any self-authored files. Doing so will fail, since variable
declarations and function definitions in your code files will be globally scoped.
To require
/import
your self-authored code, use the Separate or Bundled project structure.
# Separate
Using the above trivia skill example, let's assume you already have a solid idea of what the product is going to look like, but realize your skill might have more complex requirements, since you'd like to:
- author and require some elaborate logic (e.g. to gather metrics) at runtime
- collaborate with friends on creating the skill
- divide the code into distinct areas of concern
In this scenario, the separate project structure might be the most meaningful.
Use Separate when:
- it's necessary to
require
/import
self-authored files - multiple developers might be collaborating on different divisions of code
- project size is medium
# Generation
There are two ways to generate a project with a separate structure.
You can use generation flags like this:
litexa generate quiz-trivia-separate --bundling-strategy npm-link
or, if you aren't using flags:
litexa generate quiz-trivia-separate
and select the following answer when prompted:
? How would you like to organize your code? As modules.
# Structure
A separate project would look something like this:
.
├── README.md
├── artifacts.json
├── lib
│ ├── index.js
│ ├── logger.js
│ ├── package.json
│ ├── utils.js
│ └── utils.spec.js
├── litexa
│ ├── assets
│ │ ├── icon-108.png
│ │ └── icon-512.png
│ ├── main.js
│ ├── main.litexa
│ ├── main.test.litexa
│ └── package.json
├── litexa.config.js
└── skill.js
Here's a full breakdown of all the files and directories you could have in a separate Litexa project:
litexa.config.(json|js|ts|coffee)
file is the Litexa configuration. A Litexa project is any directory with a valid Litexa configuration file.skill.(json|js|ts|coffee)
file contains a subset of the information found in an Alexa skill manifest (opens new window). Placeholders within (e.g. skill summary and description) should be replaced according to the skill's usage.artifacts.json
file captures information about the project, such as the skill ID for each deployment or the ARN of lambdas (and the Git commit hash, when using Git). Please refer to the artifacts.json guidelines for information on sharing this file.tsconfig.json
andtslint.json
files exist if you use TypeScript to configure your project. They contain your project configuration's compilation and linting settings.package.json
is a standard npm file and is necessary when you have npm packages you would like to depend on but that will not be shipped with the skill. Typically these are build tools and compile-time extensions.package-lock.json
is the standard npm lock file that is responsible for deterministic installation of your project dependencies.node_modules
contains all of the packages you installed with npm as specified in the package.json file. These packages will NOT be deployed with your skill.README.md
file contains information about your generated project's structure.lib
directory contains a locally managed npm package. The directory name is arbitrary and you can add analogous directories, as needed. The directory contains:package.json
is a standard npm file and is necessary to recognize this directory as an npm package. You should set the entry-point and package name within.*.(js|ts|coffee)
files are your code files.*.spec.(js|ts|coffee)
files are Mocha tests files for your code..mocharc.json
is the configuration file for Mocha.
litexa
directory contains your assets, Litexa files, and skill logic:*.litexa
files are the Litexa language files.*.(js|ts|coffee)
files are code files. Any functions or variables you define here are visible within the states defined in your.litexa
files.assets
contains any images, videos and sounds you'd like to deploy with your project.languages
contains a directory per additional language you'd like to support, beyond your default language (see Localization for more details).package.json
is a standard npm file and is necessary when you have npm packages you would like to depend on and deploy with your skill.package-lock.json
is the standard npm lock file that is responsible for deterministic installation of your project dependencies.node_modules
contains all of the packages you installed with npm as specified in the package.json file. These packages WILL be deployed as a copy along with your handler.tsconfig.json
andtslint.json
files will exist if you chose TypeScript as the source-code language for your project. They will contain your project code's compilation and linting settings.
NOTE
The lib
directory is a separately managed dependency. Thus, you are free to structure your code in any way you see fit
as long as it is a valid npm package that npm can install in the litexa
directory. You can also extend and replicate
this pattern by creating new top level directories that are local npm packages, and importing those in the litexa
directory's package.
Further details on using local Node packages can be found here: NPM Local Paths (opens new window)
# Up and Running
At minimum, you need to run npm install
from your litexa
directory (this will install any external directories
you've required, such as lib
by default).
Unless you're using TypeScript (see additional steps below), you should then be able to run litexa test
and
litexa deploy
!
Additional TypeScript Setup
- If you chose TypeScript as the language for your configuration files you need to run the following commands from your project's root directory.
- If you chose TypeScript as the language for your source code files, you need to run the following
commands from within your project's
lib
directory.
npm install
npm run compile
Note, that the following utility scripts will also compile your configuration files, when run from your project's
root directory (assuming you've run npm install
):
npm run test
npm run deploy
Finally, to link your now compiled TypeScript packages to your Litexa project, run the following in the litexa
directory:
npm install
# Using external packages
If you want to add external runtime dependencies that should be deployed with your Litexa project code, you can install them
- in one of your locally required package directories (e.g.
lib
), or - directly in the
litexa
directory
by running:
npm install --save [your dependency]
Dev Dependencies
In your locally managed packages, be sure to save any packages you do not want deployed for availability during runtime
as devDependencies
. This is done by using the flag --save-dev
instead of --save
.
Importantly, this avoids unnecessarily bloating the size of your deployed skill.
# Bundled
Again using the above trivia skill example, let's assume you know exactly what your product will look like. In addition
to the separate
strategy conditions, you realize you might need:
- code layering (e.g. if you wanted to communicate with your own trivia server via a network layer)
- increased project size due to growing game logic and/or content
In this scenario, the bundled project structure might be the most meaningful. This approach will create a single, compressed executable (bundled with any package dependencies).
Use Bundled when:
- it's necessary to
require
/import
self-authored files - multiple developers might be collaborating on the skill
- code architecture requires layering (e.g. separate layers for business logic and presentation)
- project size is large
# Generation
There are two ways to generate a project with a bundled structure.
You can use generation flags like this:
litexa generate quiz-trivia-bundled --bundling-strategy webpack
or, if you aren't using flags:
litexa generate quiz-trivia-bundled
and select the following answer when prompted
? How would you like to organize your code? As an application.
# Structure
A bundled project would look something like this:
.
├── README.md
├── artifacts.json
├── lib
│ ├── components
│ │ ├── logger.js
│ │ └── utils.js
│ ├── index.js
│ └── services
│ └── time.service.js
├── litexa
│ ├── assets
│ │ ├── icon-108.png
│ │ └── icon-512.png
│ ├── main.litexa
│ └── main.test.litexa
├── package-lock.json
├── package.json
├── litexa.config.js
├── skill.js
├── test
│ ├── components
│ │ └── utils.spec.js
│ └── services
│ └── time.service.spec.js
└── webpack.config.js
Quick Overview
Alongside creating the configuration files in your project's root directory, this strategy generates the following three top level directories:
litexa
directorylib
directory with a hierarchy intended to help organize your code (components, services, etc.)test
directory that mirrors the hierarchy found inlib
, and should contain any tests
Here's a full breakdown of all the files and directories you could have in a bundled Litexa project:
litexa.config.(json|js|ts|coffee)
file is the Litexa configuration. A Litexa project is any directory with a valid Litexa configuration file.skill.(json|js|ts|coffee)
file contains a subset of the information found in an Alexa skill manifest (opens new window). Placeholders within (e.g. skill summary and description) should be replaced according to the skill's usage.artifacts.json
file captures information about the project, such as the skill ID for each deployment or the ARN of lambdas (and the Git commit hash, when using Git). Please refer to the artifacts.json guidelines for information on sharing this file.tsconfig.json
andtslint.json
files exist if you use TypeScript to configure your project. They contain your project configuration's compilation and linting settings.package.json
is a standard npm file and is necessary when you have npm packages you would like to depend on but that will not be shipped with the skill. Typically these are build tools and compile-time extensions.package-lock.json
is the standard npm lock file that is responsible for deterministic installation of your project dependencies.node_modules
contains all of the packages you installed with npm as specified in the package.json file. These packages will NOT be deployed with your skill.README.md
file contains information about your generated project's structure.lib
directory contains anindex.(js|ts|coffee)
file, which is the webpack entry-point for your application. Whatever you export in this file will be visible and accessible in Litexa (via the compiledmain.min.js
). Additionally, it should contain all of your skill's non-Litexa code, and can be divided into layers:components
directory could contain your code components (comes with simple logger/utils examples, to get you started).services
directory could contain your service code (comes with a simple time.service example, to get you started).data
directory could contain any data access layer code.*.(js|ts|coffee)
files are your code files.
test
directory mirrorslib
and contains tests for each of your files.*.spec.(js|ts|coffee)
Mocha tests files for your code.
litexa
directory contains your assets, Litexa files, and skill logic:*.litexa
files are the Litexa language files.*.(js|ts|coffee)
files are code files. Any functions or variables you define here are visible within the states defined in your.litexa
files.assets
contains any images, videos and sounds you'd like to deploy with your project.languages
contains a directory per additional language you'd like to support, beyond your default language (see Localization for more details).tsconfig.json
andtslint.json
files will exist if you chose TypeScript as the source-code language for your project. They will contain your project code's compilation and linting settings.
# Up and Running
First, you will need to run npm install
from your project's root directory, to install any dependencies.
You will then need to compile your code (this will generate the main.min.js
bundle that exposes your code to the
Litexa context). To do so, you can either explicitly npm run compile
, or implicitly compile your code using the
utility scripts for testing/deploying your project:
npm run test:litexa
npm run deploy
Utility Scripts
Check the additional scripts in package.json
which have been provided to facilitate compiling, testing, deploying,
and linting your project.
# Using External Packages
If you want to add external runtime dependencies that should be deployed with your Litexa project code, you can install
them in your project's root directory using npm install --save [your dependency]
. If the dependency is only needed
for development (and not required at runtime), use --save-dev
instead of --save
.
# Testing
The bundled strategy comes pre-configured with the generated tests to work with Mocha, Chai, and Sinon, to help you
get started. The Mocha configuration file (.mocharc.json
) can be found in your project's root directory, and the
testing scripts can be found in package.json
(prefixed with test).
If you already have a preferred testing stack, please modify this setup to suit your needs.
# Guidelines
# artifacts.json
As seen above, each of the 3 strategies' project structure contains an artifacts.json
file with certain skill
information (similar to the traditional .ask/config
). This file is relevant for anybody collaborating on the skill,
and should be shared accordingly.
DANGER
If you use the @litexa/deploy-aws
extension to deploy your skill,
artifacts.json
will also contain sensitive information such as the skill's AWS configuration, and should therefore
not be shared publicly. Make sure to use a private repository or other means of sharing the file, if you plan on
distributing your skill project publicly.
# Credential Management
Because Litexa requires a developer account for deployment, we recommend reviewing the documentation for Developer Account Management (opens new window) and, if you are working in a team, Team Account Best Practices (opens new window).
AWS Credentials
If you are using @litexa/deploy-aws
for deployment, please also review:
← Localization Testing →