-
-
The Great British Web App
I think I've figured out the next break-out TV competition show: The Great British Web App
Round 1: The Microsite
Each team is presented with a PSD and a Word doc. You've got 1 hour to slice up the images, mark up the content and deploy a microsite advertising an event. The judges are harsh on anyone demoing on localhost.
Round 2: The Magazine
Using the tools, frameworks and languages of your choice, design, develop and deploy a magazine-style web site with full CMS and social media share buttons.
Teams are judged on semantic markup, SEO friendliness and accessibility audit score.
Round 3: The Masterpiece
Your chance to show off. You have 4 hours to build the shiniest, scrollbar-misusing, WebGL-heavy, experimental web masterpiece possible to match the client brief "Anything, as long as it pops!".
You only get points if it's mobile-friendly and works on IE 6.
Prize
The Winners of the Grand Finale get a copy of Dreamweaver 4 and enrolled in a Coursera course on how to retrain as a baker...
Bonus Technical challenge for the celebrity edition
Rebuild a classic HTML element using the latest web technologies - implement
<marquee>
using Web Components or<blink>
using Web Sockets. -
Web Components vs Vue Components
I've been doing a lot of work in Vue recently so when I was asked to evaluate using Web Components on an upcoming project, I approached it with a Vue-ish mindset.
I've not really kept my eye on Web Components for the last couple of years beyond seeing original proposals being superceded and import specs being replaced. Just seeing those things on the periphery were enough to make me think "Meh... I'll have a look later when it's all died down".
Now, I know that Web Components !== Vue. But, I was interested in what knowledge could be migrated from one technology to the other. If I were building an actual web app, I'd definitely use Vue. Building a boxful of reusable, shareable UI elements, though... let's find out.
I'm not going to build anything too complex to start with. How about an "Planet Summary" panel? A simple panel that renders summary information about a planet given a JSON object.
I have an API that returns JSON information about where in the sky to find planets when given your latitude and longitude. For example, if you're standing slightly south of the centre of Berlin and want to know where Venus is, you'd make this request:
https://planets-api.awsm.st/venus/52.5/13.4
And the response would be:
{ "name": "Venus", "number": 1, "colour": 1, "colleft": 24, "colright": 25, "alt": 13.043427032890424, "az": 290.3495756869397, "dec": 22.661411404345362, "ra": 110.21545618074397, "H": 98.18491228623316, "eclon": 108.59563862950628, "eclat": 0.5200939814134588, "illum": 0.9918628383385676, "r": 0.7192422869900328, "dist": 1.7155717469739922, "mag": -3.909377586961354, "elong": 0, "pa": 0, "p": 1, "description": { "altitude": "Barely above the horizon", "azimuth": "West" }, "visible": false }
In this case, it determines Venus isn't visible because, even though it's above the horizon, it's not bright enough given the time of day (about 6pm).
We want to make a little UI card that displays this information.
Mapping Vue features to Web Components
Vue Web Component Notes name class name data instance properties props attributes these are not reactive by default. Attributes have to be specifically observed (see watch
).watch attributeChangedCallback first, register your watched attributes with `observedAttributes` then process them in attributeChangedCallback computed getters methods class methods mounted connectedCallback called async so the component may not be fully ready or may have been detached. Use Node.isConnected to protect against calling a dead node componentWillUnmount disconnectedCallback style block style block inside template styles are scoped by default template block literal template JS literal templates (backtick strings) are nowhere near as powerful for templating as an actual template library. Vue template features such as `v-for` can be replicated with vanilla JS but a single-purpose template library (such as `lit-html`) is a good idea. NOTE: I am deliberately not using Webpack. I realise that actual applications would be using additional tooling but I want to see what we can do without it.
The first thing that clicked with me was when I realised that computed properties and getters are identical. Nice.
Here's Vue code to return the planet name or a default string:
computed: { name() { return this.planet.name || ''; }, }
And Web Component:
get name() { return this.planet.name || ''; }
Well, that was easy (and trivial).
The same goes for defining the custom element for use in the DOM
Vue:
components: { "planet-summary": PlanetSummary }
Web Components:
customElements.define("planet-summary", PlanetSummary);
The only real difference at this level is the data binding. In Vue, props passed from a parent element to a child are automatically updated. If you change the data passed in, the child updates by default. With Web Components, you need to explicitly say you want to be notified of changes.
This is basically the same as setting a
watch
in Vue. Data that changes in a slightly less tightly-bound fashion can be watched and the changes trigger updates further down.Watches
Watches in Vue:
watch: { altitude(newValue, oldValue) { ... } }
With Web Components, registering a watch and reacting to changes are separate:
static get observedAttributes() { return ['altitude']; } attributeChangedCallback(name, oldValue, newValue) { if(name === 'altitude') { ... } }
Templating
Vue contains full templating support – for loops, conditional rendering, seamless passing around of data. Natively, you have literal templates and that's about it.
To create a list of planets, you'd use the
v-for
directive and loop over your planets array.Vue:
<ul> <li v-for="planet in planets"> <planet-summary :planet="planet"></planet-summary> </li> </ul>
Web Component
<ul> ${this.planets.map(planet => ` <li> <planet-summary planet='${JSON.stringify(planet)}'></planet-summary> </li> `).join('')} </ul>
The
join
is there because we're creating an HTML string out of an array of list items. You could also accomplish this with a reduce.Boilerplate
With Web Components, your component lives in the Shadow DOM so you are responsible for updating it yourself. Vue handles DOM updates for you.
Here is a basic render setup:
constructor() { super(); this._shadowRoot = this.attachShadow({ mode: "open" }); this.render(); } render() { this._shadowRoot.innerHTML = ''; this._shadowRoot.appendChild(this.template().content.cloneNode(true)); }
This needs to be explicitly included in every component as they are standalone whereas Vue automatically handles DOM updates.
CSS
Due to the fact that Web Components live in a separate document fragment, There are complications around sharing styles between the host page and the component which are nicely explained on CSS Tricks. The biggest benefit, on the other hand, is that all styles are scoped by default.
Vue without Webpack (or other tooling) also has its own complications around styles (specifically scoping styles) but if you're building a Vue application, it is much more straightforward to specify which styles are global and which are scoped.
Summary
Here is the Vue Planet Summary and the source of planet-summary-vue.js.
Here is the Web Component Planet Summary and the source of planet-summary.js.
Bonus: here's a Planet List Web Component which includes the Planet Summary component. And the source of planet-list.js
All in all, pretty much everything between basic Vue Components and Web Components can be mapped one-to-one. The differences are all the stuff around the basic construction of the components.
I'd say that if you're looking to build completely standalone, framework-free reusable components, you'll be able to accomplish it with the Web Components standard. You just might have a bit of extra lifting and boilerplate to deal with.
On the other hand, if you're already planning on building a full web application with data management and reactive components, use the tools available to you.
-
Sponsored Events on the Blockchain
Sponsored Event
In my day job, I’m responsible (among other things) for our efforts to integrate block chain and supply chain. Most of this relies on Smart Contracts. In order to learn more about them, I did a project last year that let me get in-depth.
The idea came about while my wonderful other half was organising a sponsored walk – Museum Marathon Edinburgh. It should be possible to create a sponsored event then manage funds and pledges through a smart contract. Unfortunately, I didn't get the project completed in time but I did manage to build Sponsored Event (possibly my most uninspired project name ever).
This can be used to manage, collect and distribute donations for any kind of charity event – sponsored walk, climb, run, pogo-stick marathon, etc.
No more chasing people for money after the event. No need to worry about how or whether the money makes it to the charity.
This contract also allows cancellation and withdrawal from the event. In that case, the participant's initial sign-up fee is transferred to the receiving charity but any pledges are returned to the sponsor.
Additional information about the event (description, title, images) should be stored off-chain in another database.
I built it almost 12 months ago but just updated it to use the latest version of Solidity. Due to the fast-paced nature of these things, it may or may not still work. Who knows?
Web App Structure
The web app uses
web3.js
to interact with the smart contractSponsoredEvent.sol
. It can also interact with a separate content database to keep as much non-critical data off the blockchain as possible.
Key Concepts
The Event
An event for charity where someone must complete all or part of something. In exchange someone else pledges to give money to a recipient.
The Recipient
The charity or body receiving the funds at the end. They don't need to do anything except have an account capable of receiving the funds.
The Organiser
The person creating the event specifying the name, date, description and designating the account of The Recipient. This account is the owner of The Event.
The Participant
The person actually taking part in The Event. This person signs up for the event and commits to taking part. They are given a unique URL which The Sponsor can use to pledge money. Participants are charged a sign-up fee.
The Sponsor
The source of the funds. This party has promised to donate money to The Recipient if The Participant takes part in The Event. They can include a message along with their pledge.
Cancellation
If the event is cancelled, all pledged money is automatically returned to The Sponsor. Sign-up fees are returned to The Participant.
Withdrawal from the event
If The Participant withdraws, all money pledged to them is automatically available for The Sponsor to reclaim. The participant's sign-up fee is not returned.
Ending the event
The Organiser can mark an event as Ended. This will transfer completed pledges and sign-up fees to The Recipient.
Retrieval of funds
Once the event has ended, The Sponsor is able to reclaim any funds donated to Participants who did not complete the event. The funds are not automatically returned as The Event may not have enough to cover the transaction fees.
Closing the contract
After a period of time following the end of an event, The Organiser will close the event. This will transfer any remaining balance to The Recipient.
Contract Lifecycle
Each Sponsored Event contract starts when The Organiser creates it and deploys it on the blockchain. From that point, The Participants can sign up and The Sponsors can make pledges.
Source
You can get the source on github and deploy it against a test network or run Ganache locally. Whatever you do, don't throw actual money against it. That would be a terrible idea.
-
It's Art, I tell you!
After many years of meaning to do it and not actually doing it, I decided to open an Etsy store. It's not my first online print store. In fact, one of the key reasons I ever learned HTML, CSS and PHP was to build an online store for my artwork back in... 2002? Seriously? Seventeen years ago...?
Anyways... I've put in a few prints so far, mostly from the Octoplural series of paintings although my current favourite is the My Day Flowchart.
I really like how I could tie Etsy together with Printful so the prints are generated on demand rather than me holding a lot of stock which is how we did it back in the olden days...