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.
(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
- Download as zip, unzip it, and init Git/flow.
- 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
- Or, copy repository? .gitignore? Then, init Git/flow.
- Or, start from scratch.
From scratch
- Git/flow
- .gitignore (GitHub can generate it, if repo created there.)
- README.md (or index.html for GHP? Separate branch?)…
Git/flow
- Have Gitflow installed globally.
- Initialize:
$ git flow init --defaults
creates a local development repo, if wasn't cloned from a skeleton or GitHub. Switches branch to develop.
Metadata
- Edit {package,bower}.json. DRY?
Remote
- GitLab: create repo there, then copy canonical URL.
- Set remote:
$ git remote add origin https://gitlab.com/$ACCOUNT/$PROJECT
- Use canonical URLs in package.json (homepage, repository, bugs), BJ, etc.
- Go public
Setup Git
Useful .git/config, or global, settings:
- Cache passwords:
$ git config --global credential.helper "cache --timeout=9999"
Cf git help credential-cache (or man git-credential-cache). - 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". - Bash aliases, prompt, and completion fix.
Go public
Release early and often!FLOSS motto
- Release:
$ git checkout master; git merge develop; git tag 0.0.1 $ git push --force
- Back to development:
$ git checkout develop
It works!
- Prerequisites
- Dependencies
- Environments
- Run
- Watch
Dependencies
- Versions: be specific.
Use the source, Luke!
: we prefer sources over package managers' repositories: use URL to Git (typically) repo in {package,bower}.json. Public or local.- 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!
- 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.)
$ npm install; bower install
- Distribution: map files we use to (copy to) our ./dist/.
- CDN: see under Templates→Double Macchiato→Helpers→cdn_script, et al
Environments
- Set PORT, or run temporarily with:
$ PORT=3099 cake start browser
- DOMAIN?
- Not config.coffee — feature toggling.
- PM2: ecosystem.coffee.
- Sane defaults: during build-time, prefer crashing when misconfigured, but never at runtime.
Run
$ cake start browser
SDLC
- Wireframes: UI/features specifications
- APIs: server-side/services specifications
- Continuous
Wireframes
Content
- OOA: dictionary (inventory) of nouns and verbs. Or, ERD-like, domains and properties?
- Information architecture
POP
- Prototyping on paper (POP)
- Extremes first: "deep" RWD, instead of narrow first, aka mobile first, in the olden days of "shallow" RWD.
- Very narrow: break words, never scroll horizontally.
- Very wide: how to avoid letterboxing? What content can be spread horizontally? Columns?
- Input methods: pointer/touch (adapt/consolidate?).
Screens
- Content to display/hide when navigating within SPA.
- List screens. Per SPA. ("Screen" includes modals, mutations… anything that's recorded in navigation history, ie back button applies. At least?)
- Widgets: inventory (sub)components of screens; separate list for recurring.
URLs
- URL is UI: TBL's bar napkin
- Hierarchical navigation, directories: trailing slash, redirect.
- Redirect changed/misspelled URLs; search (cf rel:search)?
- L10n prefix
- Query: KV dictionary, unordered, named, optional, built-in form submission.
- History API
- Bookmarks
- Method semantics? Fragment?
Specifications
Screen | URL | Selector | |
---|---|---|---|
Favorites | /favs | #favs | … |
Item | /items/:id | #item | … |
Catalog | /items/ | #catalog | Listing. (Redirect if missing trailing slash.) |
Navigation
- Nav conceptual structure/organization; cf "lost in hyperspace".
- Also: redirections (eg root(s), auth' dependent), screens without URLs (no history tracking)…
SPAs
- Single Page App: combine screens into (one or more) SPAs to avoid full page rendering.
- Eg: public.html, logged-in.html, admin.html, landing.html.
- When/where to render?
- Templates
- Routing
- History API
When/where to render?
- Server-side or in browser?
- Build-time or run-time? Both?
Templates
- Per SPA; eg: public.html.coffee, logged-in.html.coffee, admin.html.coffee, landing.html.coffee.
- i18n/L10n: rendered into static assets once; eg app.language.html.coffee will be rendered into app.en.html, app.es.html, etc.
- CoffeeScript modules exporting an HTML renderer:
# public.-.html.coffee module.exports=renderable (lang)-> html5bp {lang},-> title 'Skeleton (Public)' #…
(See skeleton for useful "templates".)
- Source ordering
Routing
- Express routing: order significant: decreasing specificity
- 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'
- 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.) - 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. - (Server/client side (SS/CS) scaffolding, helpers… forthcoming.)
History API
- 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'
- 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'
- 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
- Mockups that work in browser!
- Top-down…
- Nav links (backdoor)
Layouts
- RWD, eg:
- Narrow (single column): questionnaire screen has outline/nav in collapsed drawer, sliding in from right (align:end)
- Wide (double): questionnaire in right column, outline/nav in left, always expanded
- Huge (triple): wide, plus preview of results in a third column
- Patterns…
- Widgets
- Nav bars, dropdowns, modals…
APIs
- No HTML on the wire. [Meteor]
- WS or AJAX? HTTP/2?
Continuous
Test
- Why?
- Libraries (independent)
- Server-side: APIs
- Client-side: unit vs integration/end-to-end
- Automated:
$ cake test
Client-side
- Standalone HTML: render template to load unit tests
- Partial template to embed into app for integration/end-to-end tests
- Client-side code to run, and maybe defer loading of tests
- Styling (mixins) for Mocha's reporter
Release
- Gitflow: merge feature branch into develop
- Version: bump
- Update README: release notes, assign version to tickets
- Merge develop into master — release:
$ go master; git merge develop
- Tag commit with version
Topics
Editable (WYSIWYG)
i18n/L10n
Data Modeling and I/O
Auth²
Styleguide
--
The real world is a special case