Constitution: a Method to the Madness

Systematic web apps development (notes towards…). The method I follow with my still work in progress Constitution stack.

Project

Initialize codebase, workflow.

  1. Skeletons: quick start
  2. Metadata
  3. Remote: distributed, collaboration
  4. It works!

(The least important step. Nu, from a marketing perspective (funnel), assuming a long tail distribution of adoption (time spent with this stack), it makes sense to emphasize painless installation and… but, at what price? I do 1,000 hours scale projects. It's astonishing how frameworks fuss about the first five minutes, and hardly give thought to the rest. Market failure much?)

Skeletons

  1. Download as zip, unzip it, and init Git/flow.
  2. Or, clone it:
    $ mkdir $PROJECT/Code; cd $PROJECT/Code # (How I usually name a repo.)
    $ git clone $SKELETON .
    
    But, don't need history:
    $ git clone --depth 1 --branch master $SKELETON .
    Records cloned remote as "origin". Remove:
    $ git remote rm origin
    Or keep and rename that remote, so can diff against future skeleton updates?
    $ git remote rename origin skeleton
  3. Or, copy repository? .gitignore? Then, init Git/flow.
  4. Or, start from scratch.

From scratch

  1. Git/flow
  2. .gitignore (GitHub can generate it, if repo created there.)
  3. README.md (or index.html for GHP? Separate branch?)…

Git/flow

  1. Have Gitflow installed globally.
  2. Initialize:
    $ git flow init --defaults
    creates a local development repo, if wasn't cloned from a skeleton or GitHub. Switches branch to develop.

Metadata

  1. Edit {package,bower}.json. DRY?

Remote

  1. GitLab: create repo there, then copy canonical URL.
  2. Set remote:
    $ git remote add origin https://gitlab.com/$ACCOUNT/$PROJECT
  3. Use canonical URLs in package.json (homepage, repository, bugs), BJ, etc.
  4. Go public

Setup Git

Useful .git/config, or global, settings:

  1. Cache passwords:
    $ git config --global credential.helper "cache --timeout=9999"
    Cf git help credential-cache (or man git-credential-cache).
  2. Force HTTPS for when (public) Wi-Fi blocks SSH port:
    $ git config --global url.https://.insteadof git://
    Cf git help config.
    $ git config push.default current
    so can just "git push" from separate local clones of different branches, particularly "gh-pages".
  3. Bash aliases, prompt, and completion fix.
Etc.

Go public

Release early and often!FLOSS motto
  1. Release:
    $ git checkout master; git merge develop; git tag 0.0.1
    $ git push --force
  2. Back to development:
    $ git checkout develop

It works!

  1. Prerequisites
  2. Dependencies
  3. Environments
  4. Run
  5. Watch

Dependencies

  1. Versions: be specific.
  2. Use the source, Luke!: we prefer sources over package managers' repositories: use URL to Git (typically) repo in {package,bower}.json. Public or local.
  3. When using private repositories on GitLab, set up SSH keys to allow (passwordless) access, when using SSH based URLs (git://gitlab.com/…), or generate access tokens for HTTPS URLs (git+https://…) — don't use your GitLab account credentials!
  4. Build? Source shouldn't contain compiled files, we must build them after installing (which clones(?) the tagged version we specified). (Package managers' repositories (npm, Bower) usually publish pre-built packages.)
  5. $ npm install; bower install
  6. Distribution: map files we use to (copy to) our ./dist/.
  7. CDN: see under Templates→Double Macchiato→Helpers→cdn_script, et al

Environments

  1. Set PORT, or run temporarily with:
    $ PORT=3099 cake start browser
  2. DOMAIN?
  3. Not config.coffee — feature toggling.
  4. PM2: ecosystem.coffee.
  5. Sane defaults: during build-time, prefer crashing when misconfigured, but never at runtime.

Run

  1. $ cake start browser

SDLC

  1. Wireframes: UI/features specifications
  2. APIs: server-side/services specifications
  3. Continuous

Wireframes

Content

  1. OOA: dictionary (inventory) of nouns and verbs. Or, ERD-like, domains and properties?
  2. Information architecture

POP

  1. Prototyping on paper (POP)
  2. Extremes first: "deep" RWD, instead of narrow first, aka mobile first, in the olden days of "shallow" RWD.
    1. Very narrow: break words, never scroll horizontally.
    2. Very wide: how to avoid letterboxing? What content can be spread horizontally? Columns?
  3. Input methods: pointer/touch (adapt/consolidate?).

Screens

  1. Content to display/hide when navigating within SPA.
  2. List screens. Per SPA. ("Screen" includes modals, mutations… anything that's recorded in navigation history, ie back button applies. At least?)
  3. Widgets: inventory (sub)components of screens; separate list for recurring.

URLs

  1. URL is UI: TBL's bar napkin
  2. Hierarchical navigation, directories: trailing slash, redirect.
  3. Redirect changed/misspelled URLs; search (cf rel:search)?
  4. L10n prefix
  5. Query: KV dictionary, unordered, named, optional, built-in form submission.
  6. History API
  7. Bookmarks
  8. Method semantics? Fragment?

Specifications

ScreenURLSelector
Favorites/favs#favs
Item/items/:id#item
Catalog/items/#catalogListing. (Redirect if missing trailing slash.)

Navigation

  1. Nav conceptual structure/organization; cf "lost in hyperspace".
  2. Also: redirections (eg root(s), auth' dependent), screens without URLs (no history tracking)…

SPAs

  1. Single Page App: combine screens into (one or more) SPAs to avoid full page rendering.
  2. Eg: public.html, logged-in.html, admin.html, landing.html.
  3. When/where to render?
  4. Templates
  5. Routing
  6. History API

When/where to render?

  1. Server-side or in browser?
  2. Build-time or run-time? Both?

Templates

  1. Per SPA; eg: public.html.coffee, logged-in.html.coffee, admin.html.coffee, landing.html.coffee.
  2. i18n/L10n: rendered into static assets once; eg app.language.html.coffee will be rendered into app.en.html, app.es.html, etc.
  3. CoffeeScript modules exporting an HTML renderer:
    # public.-.html.coffee
    module.exports=renderable (lang)->
    	html5bp {lang},->
    		title 'Skeleton (Public)'
    		#…
    

    (See skeleton for useful "templates".)

  4. Source ordering

Routing

  1. Express routing: order significant: decreasing specificity
  2. Route all URLs to corresponding SPA, so they can be bookmarked, shared.
    app # Express.
    # Public (anonymous) SPA.
    .all /\/(..)\/(|login|logout|terms)$/,(req,res)->res.sendfile ASSETS+"/public.#{req.params[0]}.html"
    # Admin SPA.
    .all /\/(sys|error)$/,(req,res)->res.sendfile ASSETS+'/admin.html'
    
  3. Redirects: eg, to pick language prefix:
    .all /\/([a-z]{2})?$/i,(req,res)->res.redirect "/#{pick_language req}/"
    (Redirect to appropriate SPA based on optional path parameter, session (cookie), or UA preferences.)
  4. Directories in URL path, for namespacing collections:
    # Directories: redirect to append slash.
    .all /\/(..)\/(items|profiles|help)$/,(req,res)->res.redirect req.path+'/'
    allowing for URLs like /en/items/foo and /en/items/, not /en/items.
  5. (Server/client side (SS/CS) scaffolding, helpers… forthcoming.)

History API

  1. Capture navigation internal to an SPA; eg:
    ## app.coffee
    page.base "/#{lang}"
    page '/favs',->show_screen '#favs'; set_title 'Favorites'
    page '/i/',->show_screen '#dir'; set_title 'Directory'
    page '/i/:id',->show_screen '#item'; set_title 'Item'
    
  2. Render absolute URLs, so can navigate up/down the URL path, eg app.-.html.coffee:
    a href:"/#{lang}/i/123",'Item'
    a href:"/#{lang}/help/me",->i '.fa.fa-question';text 'Help'
    a href:"/#{lang}/flow",->i '.fa.fa-shopping-cart';text 'Workflow'
    
  3. Screens (HTML <section>s) have unique IDs, which show_screen copies to an attribute on <body>:
    $('body').attr 'data-screen',p
    so can easily target screens in CSS, eg (Stylus):
    a
    	header &
    		color inherit
    		[data-screen="#favs"] &.fa-star
    		[data-screen="#profile"] &.fa-user
    			color white
    
    (But, second thoughts about this example: mixing state with styling smells…)

Grayscreening

  1. Mockups that work in browser!
  2. Top-down…
  3. Nav links (backdoor)

Layouts

  1. RWD, eg:
    1. Narrow (single column): questionnaire screen has outline/nav in collapsed drawer, sliding in from right (align:end)
    2. Wide (double): questionnaire in right column, outline/nav in left, always expanded
    3. Huge (triple): wide, plus preview of results in a third column
  2. Patterns…
  3. Widgets
    1. Nav bars, dropdowns, modals…

APIs

  1. No HTML on the wire. [Meteor]
  2. WS or AJAX? HTTP/2?

Continuous

  1. Uptodate? Secure?
  2. Test
  3. Release
  4. Deploy
  5. Publish

Test

  1. Why?
  2. Libraries (independent)
  3. Server-side: APIs
  4. Client-side: unit vs integration/end-to-end
  5. Automated:
    $ cake test

Client-side

  1. Standalone HTML: render template to load unit tests
  2. Partial template to embed into app for integration/end-to-end tests
  3. Client-side code to run, and maybe defer loading of tests
  4. Styling (mixins) for Mocha's reporter

Release

  1. Gitflow: merge feature branch into develop
  2. Version: bump
  3. Update README: release notes, assign version to tickets
  4. Merge develop into master — release:
    $ go master; git merge develop
  5. Tag commit with version

Topics

Editable (WYSIWYG)

i18n/L10n

Data Modeling and I/O

Auth²

Styleguide


--
The real world is a special case