Building multiple apps from the same source

This is the structure we use. We run three Meteor apps on Galaxy, a main app and 2 “micro-service” apps that are server side only that are called from the main app. All 3 apps are checked into the same git repository. There are a few key things that we do that makes it easier to reason about our app and also make it easier to refactor code. We have a very extensive design document that covers many more details such as naming conventions, etc. but I don’t want to post it here:

  1. We always use ES6 imports and exports to control code load order including with global code such as Meteor packages, import {Meteor} from 'meteor/meteor';
  2. We use an index.js, which imports all files and re-exports the public APIs, for all our modules and certain directories where we want to be able to easily import the entire functionality of that module or directory.
  3. We use relative imports within our modules or functional areas like import foo from ‘../foo’; and absolute imports across modules like import foo from ‘/imports/api/foo’;.
  4. All the re-usable non-UI code is in /imports/api/ in the main app directory. The other apps have a symlink from their own /imports/api/ directory to the main app.
Meteor App high level directory layout
app/			# a Meteor app directory, multiple app directories are supported
builds/			# app client and server builds, if any
config/		        # settings.json and env variables for dev, staging, production
scripts/		# misc. scripts for build or testing, if any

A Meteor app directory layout
.meteor/                # Meteor package configuration and local builds
client/
  main.js               # client entry point, imports all client code
  main.css/             # imports other styles from imports/client/components, if needed
  main.html	        # tags in <head> or use package to inject like react-helmet

server/
  main.js               # server entry point, imports all server code
 
imports/
  startup/		# All app-wide, common, and startup configuration
    client/             # configuration for routes, subscriptions, or any other client side services

    server/		# configuration for users, email, oauth or any other server side services
      index.js		# imports all server bootstrap, security, config and api code
      bootstrap.js      # general configuration startup code
      security.js       # set browser and security policies
      register-api.js   # imports server only code from api/*/server and all other api code
      user-config.js	# configure user account profile and email templates

  api/			# business logic
    moduleOne/          # a unit of business logic
      index.js		# imports all module one apis and re-export public apis for outside use
      ModuleOne.js      # module one collections
      methods.js        # module one methods
      schema.js         # schema definitions for module one
      ModuleOne.tests.js # tests for module one
      server/           # module one code that runs only on the server
        index.js        # imports all server code for module one
        methods.js      # server only methods for module one, if any
        publications.js	# publications for module one

    lib/		# api utility functions and shared libraries

  client/               # client only code so changes won’t rebuild server code
    components/	        # reusable ui components
      ComponentOne.js   # contains simple, stateless React component
      componentOne.tests.js # tests for component one
      ComponentTwo/     # complex React component with subcomponents
        ComponentTwo.js # main React component which imports subcomponents
        ComponentTwoContainer.js # HOC React code to fetch data and pass state to component 
        ComponentTwoA.js # stateless React ui subcomponent
        ComponentTwoB.js # stateless React ui subcomponents
        index.js        #  imports all component two ui code and re-exports

    layouts/            # wrapper components for behaviour and visuals
    lib/                # ui utility functions and shared libraries
      index.js          # imports all lib functions and re-exports as default and for each function
    styles/		# global style definitions including 3rd party vendor styles

  packages/		# 3rd party packages that we need to modify and support, if any

node_modules/           # app NPM packages defined in package.json
public/			# fonts, images, icons, favicon
resources/		# mobile icons and splash screens
tests/			# integration tests not run by Meteor built-in test tools

EDIT: I should say that we support both web browser and Cordova mobile apps on iOS and Android from the same code base. For the UI we are using Material-UI. We have created some very basic layout components to deal with the size/layout differences for browser and mobile, but this is very little code to achieve what we need. We also had to use a different list component to get better performance on mobile, react-virtualized.

3 Likes