diff --git a/conda/js/src/helpers/api.js b/conda/js/src/helpers/api.js
index 60935f59dd15e56cfcb57c9b589a8da1ed698bf3..3afcb2ad3658045b3cf8f3055b4ceb46030910b9 100644
--- a/conda/js/src/helpers/api.js
+++ b/conda/js/src/helpers/api.js
@@ -1,4 +1,5 @@
 // @flow
+// API helpers not tied to any specific library
 import { pluralize } from './beat.js';
 import type { BeatEntity } from './beat.js';
 import type { StringObject } from '.';
@@ -13,6 +14,9 @@ let port = '5000';
 
 const toUrl = (str) => `http://127.0.0.1:${ port }/${ str }`;
 
+// curried func for calling the REST API
+// basically:
+// <response> = genApiCall(<http rest verb>)(<endpoint>)(<payload if any>)
 const genApiCall = (method) => (be: Fetchable) => async (obj: any) => {
 	const validMethods = ['GET', 'POST', 'PUT', 'DELETE'];
 	if(!validMethods.includes(method))
@@ -36,10 +40,12 @@ const genApiCall = (method) => (be: Fetchable) => async (obj: any) => {
 	return json;
 };
 
+// sets the port number for api calls
 export const setPort = (newPort: number) => {
 	port = newPort;
 };
 
+// gens all the default API funcs for an endpoint
 export const genModuleApiFuncs = (be: Fetchable) => {
 	return {
 		get: genApiCall('GET')(be),
@@ -49,6 +55,7 @@ export const genModuleApiFuncs = (be: Fetchable) => {
 	};
 };
 
+// fetches layout info from graphviz for a toolchain
 const layoutUrl = toUrl('layout');
 export const fetchLayout = async (tcName: string) => {
 	const layoutConfig = {
@@ -64,6 +71,7 @@ export const fetchLayout = async (tcName: string) => {
 	return JSON.parse(json);
 };
 
+// generates a python file from a template given some args payload
 const templatesUrl = toUrl('templates');
 const generateTemplate = async (be: string, args: {[string]: any}) => {
 	const templatesConfig = {
diff --git a/conda/js/src/helpers/beat.js b/conda/js/src/helpers/beat.js
index 41979813acc6bec9422e893cc828082dda43bfe1..228643f06d27d1716527386ea33e93e0b4f14f17 100644
--- a/conda/js/src/helpers/beat.js
+++ b/conda/js/src/helpers/beat.js
@@ -1,7 +1,10 @@
 // @flow
+// BEAT-specific helpers
 import { jsonClone } from '.';
+// all the BEAT entities
 export type BeatEntity = 'database' | 'library' | 'dataformat' | 'algorithm' | 'toolchain' | 'experiment' | 'plotter' | 'plotterparameter';
 
+// format of an instance of a beat entity in redux store
 export type BeatObject = {|
 	// name of the object
 	name: string,
@@ -11,10 +14,12 @@ export type BeatObject = {|
 	extraContents?: any,
 |};
 
+// format for the settings object
 export type BeatSettings = {|
 	prefix: string
 |};
 
+// format for an environment object (info about the available docker envs)
 export type BeatEnvironment = {|
 	name: string,
 	packages: { [string]: string },
@@ -44,6 +49,7 @@ export const BEAT_ENTITIES: BeatEntity[] = [
 	'plotterparameter',
 ];
 
+// types auto-recognized by beat.core
 export const BUILTIN_TYPES = [
 	'int8',
 	'int16',
@@ -63,6 +69,7 @@ export const BUILTIN_TYPES = [
 	'object',
 ];
 
+// result types for analyzers
 export const ANALYZER_RESULT_TYPES = [
 	'int32',
 	'float32',
@@ -74,12 +81,16 @@ Object.freeze(BEAT_ENTITIES);
 Object.freeze(BUILTIN_TYPES);
 Object.freeze(ANALYZER_RESULT_TYPES);
 
+// get toolchain name from experiment name
 export const getTcFromExpName = (expName: string) => expName.split('/').slice(1, 4).join('/');
 
+// default object for beat entity instances
 export const getDefaultEntityObject = () => ({name: '', contents: {}});
 
+// most fields/name of/in beat objects need to conform to this regex
 export const rxField = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;
 
+// how many segments (separated by '/') are in an entity's name
 export const nameSegmentsForEntity = (entity: BeatEntity) => {
 	if(entity === 'database')
 		return 2;
@@ -88,6 +99,7 @@ export const nameSegmentsForEntity = (entity: BeatEntity) => {
 	return 3;
 };
 
+// pluralizes an entity
 export const pluralize = (be: BeatEntity): string => {
 	switch(be) {
 		case 'database':
@@ -111,6 +123,7 @@ export const pluralize = (be: BeatEntity): string => {
 	}
 };
 
+// validates that a name for beat object of an entity is fine, given the names for all objects of that entity
 export const nameValidator = (be: BeatEntity, allNames?: string[] = []) => (name: string): boolean => {
 	if(allNames.includes(name)){
 		return false;
@@ -140,12 +153,16 @@ export const nameValidator = (be: BeatEntity, allNames?: string[] = []) => (name
 	return true;
 };
 
+// some editors are prime targets for better/additional validation
+
 export type ValidatorObjectField = boolean | boolean[];
 
+// only algs & libs have this extra validation right now
 export type ValidatorObject = AlgorithmValidatorObject | LibraryValidatorObject;
 
 export type ValidatorFunc = (obj: BeatObject, allObjs: BeatObject[]) => ValidatorObject;
 
+// algorithm validator info
 export type AlgorithmValidatorObject = {
 	// is algorithm name valid?
 	name: ValidatorObjectField,
@@ -161,6 +178,7 @@ export type AlgorithmValidatorObject = {
 	result0Exists: ValidatorObjectField,
 };
 
+// lots of checks for algs
 export const algorithmValidator = (obj: BeatObject, allObjs: BeatObject[]): AlgorithmValidatorObject => {
 
 	let name = false;
@@ -205,6 +223,7 @@ export const algorithmValidator = (obj: BeatObject, allObjs: BeatObject[]): Algo
 	return valid;
 };
 
+// extra validation for libs
 export type LibraryValidatorObject = {
 	// is library name valid?
 	name: ValidatorObjectField,
@@ -231,6 +250,10 @@ export const libraryValidator = (obj: BeatObject, allObjs: BeatObject[]): Librar
 	};
 };
 
+// these next several funcs, the "getValid***Obj", returns a properly-formed JSON obj,
+// optionally filling in fields with an existing obj.
+// basically they exist to keep malformed JSON from breaking the editors.
+//
 export const getValidAlgorithmObj = (data: BeatObject = {name: '', contents: {}}) => {
 	const getObj = {
 		name: '',
diff --git a/conda/js/src/helpers/index.js b/conda/js/src/helpers/index.js
index 18b4ccd76477619aaf1a06086f556b5411a70b3b..6c12503d6c56ea52424587f1a55ba1bbd8265c02 100644
--- a/conda/js/src/helpers/index.js
+++ b/conda/js/src/helpers/index.js
@@ -1,22 +1,15 @@
 // @flow
-export const objToArr = (data: any): any[] => {
-	if(!data)
-		throw new Error(`Invalid data "${ data }"`);
-
-	if(Array.isArray(data))
-		return data;
-	return Object.entries(data)
-	.map(([k, obj]) => objToArr(obj))
-	.reduce((a: any[], objs: any[]) => [...a, ...objs], [])
-	;
-};
+// basic helpers - common bits of code refactored to DRY
 
+// changes a field in an object to a different name
+// only required because keys are often mutable
 export const changeObjFieldName = (obj: {}, oldName: string, newName: string): {} => {
 	return Object.entries(obj)
 	.map(([name, val]) => [name === oldName ? newName : name, val])
 	.reduce((o, [name, val]) => ({...o, [name]: val}), {});
 };
 
+// generates a new unique key given a prefix (like "value" or "param") and possibly conflicting keys
 export const generateNewKey = (keyPrefix: string = '', existingKeys: string[]) => {
 	if(!existingKeys.includes(keyPrefix))
 		return keyPrefix;
@@ -49,7 +42,8 @@ export const getRandomBrightColor = () => {
 };
 
 // recursively sorts an object's keys in alphabetical order
-// useful for comparing (deeply nested) objects in stringified form
+// useful for comparing (deeply nested) objects in stringified form.
+// probably would be better to use another dep specialized in deeply comparing objects?
 export const sortObject = (o: any) => Object.entries(o)
 .sort(([n1, v1], [n2, v2]) => n1 > n2 ? 1 : -1)
 .reduce((o, [n, v]) => ({...o, [n]: Object((v: any)) === v ? sortObject(v) : v}), {});
diff --git a/conda/js/src/store/actionTypes.js b/conda/js/src/store/actionTypes.js
index 34c94a26d134f15d3095c5b41e2f3a6014447016..025b0004e8a98caa28bce12985400e2f0e65a2a7 100644
--- a/conda/js/src/store/actionTypes.js
+++ b/conda/js/src/store/actionTypes.js
@@ -1,4 +1,7 @@
 // @flow
+// the action types (constants) are defined here
+// if you want to add one, youll need to add the constant string to the ActionType below
+// and also add a line for the constant
 export type ActionType = 'FETCH_ALL'
 | 'SAVE_DATABASE' | 'ADD_DATABASE' | 'DELETE_DATABASE' | 'UPDATE_DATABASE'
 | 'SAVE_LIBRARY' | 'ADD_LIBRARY' | 'DELETE_LIBRARY' | 'UPDATE_LIBRARY'
diff --git a/conda/js/src/store/actions.js b/conda/js/src/store/actions.js
index 46e89a758fd0f527edf7a55dd8793fd3cc9a3bd5..c6cc7510af9e17a2e805d1a6b74f46af5fb6b4cd 100644
--- a/conda/js/src/store/actions.js
+++ b/conda/js/src/store/actions.js
@@ -1,4 +1,11 @@
 // @flow
+/* Actions for Redux
+ * all the actions for redux are defined here
+ * some actions are actually async action creators for async stuff (API calls)
+ * most are pretty simple and tied to a specific BEAT entity
+ * each entity has the same actions available, allowing lots of templating stuff
+ * these actions specify a type, using the constants in the ActionTypes
+*/
 import type {
 	ActionType,
 } from './actionTypes';
@@ -7,7 +14,6 @@ import * as Types from './actionTypes.js';
 import type { Dispatch } from 'redux';
 import { genModuleApiFuncs } from '@helpers/api';
 import { BEAT_ENTITIES } from '@helpers/beat';
-import { objToArr } from '@helpers';
 
 import type { BeatEntity, BeatObject, BeatSettings, BeatEnvironment } from '@helpers/beat';
 
@@ -22,6 +28,19 @@ export type ActionCreator = (any, any) => Action;
 
 export type ActionThunkCreator = (any) => (dispatch: Dispatch<*>) => Promise<*>;
 
+// helper to sort of flatten api response objects to arrays
+const objToArr = (data: any): any[] => {
+	if(!data)
+		throw new Error(`Invalid data "${ data }"`);
+
+	if(Array.isArray(data))
+		return data;
+	return Object.entries(data)
+	.map(([k, obj]) => objToArr(obj))
+	.reduce((a: any[], objs: any[]) => [...a, ...objs], [])
+	;
+};
+
 export const fetchAllObjects: ActionThunkCreator = () => async (dispatch: Dispatch<*>) => {
 	//console.log(`fetchAllObjects`);
 	const getFuncs = [...BEAT_ENTITIES].map(e => genModuleApiFuncs(e).get);
diff --git a/conda/js/src/store/index.js b/conda/js/src/store/index.js
index 1787e6975b70d1d52499f74ba23bdaaf0542758b..9ddcb5fdae43b736ef36660ee8eeb82667cfd071 100644
--- a/conda/js/src/store/index.js
+++ b/conda/js/src/store/index.js
@@ -1,4 +1,5 @@
 // @flow
+// builds the store and fetches the objects
 import { createStore, applyMiddleware, compose } from 'redux';
 import reducer from './reducers';
 import thunk from 'redux-thunk';
diff --git a/conda/js/src/store/reducers.js b/conda/js/src/store/reducers.js
index a60ba5da808f1bdb62706b10eea555bf1ed7f77a..9e8ca439c9a8861c9debe69458e29e559df1598b 100644
--- a/conda/js/src/store/reducers.js
+++ b/conda/js/src/store/reducers.js
@@ -1,4 +1,8 @@
 // @flow
+/* Reducers for Redux
+ * all the reducers are here.
+ * since most actions are similar (all entities have the same basic actions available) there's alot of templating that happens.
+*/
 import { combineReducers } from 'redux';
 
 import type { Action } from './actions.js';
diff --git a/conda/js/src/store/selectors.js b/conda/js/src/store/selectors.js
index b0f3463b7242fc3936cf0b40ef4eac209170c863..7277cbb1a7e9183e772dc0f6292aec4ac69916d0 100644
--- a/conda/js/src/store/selectors.js
+++ b/conda/js/src/store/selectors.js
@@ -1,4 +1,7 @@
 // @flow
+/* State selectors for our Redux store via Reselect
+ * basically a bunch of memoized shortcuts to certain state/derived state
+*/
 import { createSelector } from 'reselect';
 import type { State } from './reducers.js';
 import { getTcFromExpName } from '@helpers/beat';