CINXE.COM

Web Development Talks | Caktus Group

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"><script type="text/javascript">(window.NREUM||(NREUM={})).init={ajax:{deny_list:["bam.nr-data.net"]}};(window.NREUM||(NREUM={})).loader_config={licenseKey:"NRBR-2fdf56539d4020c5401",applicationID:"957418355"};;/*! For license information please see nr-loader-rum-1.286.0.min.js.LICENSE.txt */ (()=>{var e,t,r={8122:(e,t,r)=>{"use strict";r.d(t,{a:()=>i});var n=r(944);function i(e,t){try{if(!e||"object"!=typeof e)return(0,n.R)(3);if(!t||"object"!=typeof t)return(0,n.R)(4);const r=Object.create(Object.getPrototypeOf(t),Object.getOwnPropertyDescriptors(t)),o=0===Object.keys(r).length?e:r;for(let a in o)if(void 0!==e[a])try{if(null===e[a]){r[a]=null;continue}Array.isArray(e[a])&&Array.isArray(t[a])?r[a]=Array.from(new Set([...e[a],...t[a]])):"object"==typeof e[a]&&"object"==typeof t[a]?r[a]=i(e[a],t[a]):r[a]=e[a]}catch(e){(0,n.R)(1,e)}return r}catch(e){(0,n.R)(2,e)}}},2555:(e,t,r)=>{"use strict";r.d(t,{fn:()=>s,x1:()=>c});var n=r(384),i=r(8122);const o={beacon:n.NT.beacon,errorBeacon:n.NT.errorBeacon,licenseKey:void 0,applicationID:void 0,sa:void 0,queueTime:void 0,applicationTime:void 0,ttGuid:void 0,user:void 0,account:void 0,product:void 0,extra:void 0,jsAttributes:{},userAttributes:void 0,atts:void 0,transactionName:void 0,tNamePlain:void 0},a={};function s(e){try{const t=function(e){if(!e)throw new Error("All info objects require an agent identifier!");if(!a[e])throw new Error("Info for ".concat(e," was never set"));return a[e]}(e);return!!t.licenseKey&&!!t.errorBeacon&&!!t.applicationID}catch(e){return!1}}function c(e,t){if(!e)throw new Error("All info objects require an agent identifier!");a[e]=(0,i.a)(t,o);const r=(0,n.nY)(e);r&&(r.info=a[e])}},5217:(e,t,r)=>{"use strict";r.d(t,{gD:()=>h,xN:()=>m});r(860).K7.genericEvents;const n="experimental.marks",i="experimental.measures",o="experimental.resources",a=e=>{if(!e||"string"!=typeof e)return!1;try{document.createDocumentFragment().querySelector(e)}catch{return!1}return!0};var s=r(2614),c=r(944),u=r(384),d=r(8122);const l="[data-nr-mask]",f=()=>{const e={feature_flags:[],experimental:{marks:!1,measures:!1,resources:!1},mask_selector:"*",block_selector:"[data-nr-block]",mask_input_options:{color:!1,date:!1,"datetime-local":!1,email:!1,month:!1,number:!1,range:!1,search:!1,tel:!1,text:!1,time:!1,url:!1,week:!1,textarea:!1,select:!1,password:!0}};return{ajax:{deny_list:void 0,block_internal:!0,enabled:!0,autoStart:!0},distributed_tracing:{enabled:void 0,exclude_newrelic_header:void 0,cors_use_newrelic_header:void 0,cors_use_tracecontext_headers:void 0,allowed_origins:void 0},get feature_flags(){return e.feature_flags},set feature_flags(t){e.feature_flags=t},generic_events:{enabled:!0,autoStart:!0},harvest:{interval:30},jserrors:{enabled:!0,autoStart:!0},logging:{enabled:!0,autoStart:!0},metrics:{enabled:!0,autoStart:!0},obfuscate:void 0,page_action:{enabled:!0},page_view_event:{enabled:!0,autoStart:!0},page_view_timing:{enabled:!0,autoStart:!0},performance:{get capture_marks(){return e.feature_flags.includes(n)||e.experimental.marks},set capture_marks(t){e.experimental.marks=t},get capture_measures(){return e.feature_flags.includes(i)||e.experimental.measures},set capture_measures(t){e.experimental.measures=t},capture_detail:!0,resources:{get enabled(){return e.feature_flags.includes(o)||e.experimental.resources},set enabled(t){e.experimental.resources=t},asset_types:[],first_party_domains:[],ignore_newrelic:!0}},privacy:{cookies_enabled:!0},proxy:{assets:void 0,beacon:void 0},session:{expiresMs:s.wk,inactiveMs:s.BB},session_replay:{autoStart:!0,enabled:!1,preload:!1,sampling_rate:10,error_sampling_rate:100,collect_fonts:!1,inline_images:!1,fix_stylesheets:!0,mask_all_inputs:!0,get mask_text_selector(){return e.mask_selector},set mask_text_selector(t){a(t)?e.mask_selector="".concat(t,",").concat(l):""===t||null===t?e.mask_selector=l:(0,c.R)(5,t)},get block_class(){return"nr-block"},get ignore_class(){return"nr-ignore"},get mask_text_class(){return"nr-mask"},get block_selector(){return e.block_selector},set block_selector(t){a(t)?e.block_selector+=",".concat(t):""!==t&&(0,c.R)(6,t)},get mask_input_options(){return e.mask_input_options},set mask_input_options(t){t&&"object"==typeof t?e.mask_input_options={...t,password:!0}:(0,c.R)(7,t)}},session_trace:{enabled:!0,autoStart:!0},soft_navigations:{enabled:!0,autoStart:!0},spa:{enabled:!0,autoStart:!0},ssl:void 0,user_actions:{enabled:!0,elementAttributes:["id","className","tagName","type"]}}},g={},p="All configuration objects require an agent identifier!";function m(e,t){if(!e)throw new Error(p);g[e]=(0,d.a)(t,f());const r=(0,u.nY)(e);r&&(r.init=g[e])}function h(e,t){if(!e)throw new Error(p);var r=function(e){if(!e)throw new Error(p);if(!g[e])throw new Error("Configuration for ".concat(e," was never set"));return g[e]}(e);if(r){for(var n=t.split("."),i=0;i<n.length-1;i++)if("object"!=typeof(r=r[n[i]]))return;r=r[n[n.length-1]]}return r}},3371:(e,t,r)=>{"use strict";r.d(t,{V:()=>f,f:()=>l});var n=r(8122),i=r(384),o=r(6154),a=r(9324);let s=0;const c={buildEnv:a.F3,distMethod:a.Xs,version:a.xv,originTime:o.WN},u={customTransaction:void 0,disabled:!1,isolatedBacklog:!1,loaderType:void 0,maxBytes:3e4,onerror:void 0,ptid:void 0,releaseIds:{},appMetadata:{},session:void 0,denyList:void 0,timeKeeper:void 0,obfuscator:void 0,harvester:void 0},d={};function l(e){if(!e)throw new Error("All runtime objects require an agent identifier!");if(!d[e])throw new Error("Runtime for ".concat(e," was never set"));return d[e]}function f(e,t){if(!e)throw new Error("All runtime objects require an agent identifier!");d[e]={...(0,n.a)(t,u),...c},Object.hasOwnProperty.call(d[e],"harvestCount")||Object.defineProperty(d[e],"harvestCount",{get:()=>++s});const r=(0,i.nY)(e);r&&(r.runtime=d[e])}},9324:(e,t,r)=>{"use strict";r.d(t,{F3:()=>i,Xs:()=>o,xv:()=>n});const n="1.286.0",i="PROD",o="CDN"},6154:(e,t,r)=>{"use strict";r.d(t,{OF:()=>c,RI:()=>i,WN:()=>d,bv:()=>o,gm:()=>a,mw:()=>s,sb:()=>u});var n=r(1863);const i="undefined"!=typeof window&&!!window.document,o="undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self.navigator instanceof WorkerNavigator||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis.navigator instanceof WorkerNavigator),a=i?window:"undefined"!=typeof WorkerGlobalScope&&("undefined"!=typeof self&&self instanceof WorkerGlobalScope&&self||"undefined"!=typeof globalThis&&globalThis instanceof WorkerGlobalScope&&globalThis),s=Boolean("hidden"===a?.document?.visibilityState),c=/iPad|iPhone|iPod/.test(a.navigator?.userAgent),u=c&&"undefined"==typeof SharedWorker,d=((()=>{const e=a.navigator?.userAgent?.match(/Firefox[/\s](\d+\.\d+)/);Array.isArray(e)&&e.length>=2&&e[1]})(),Date.now()-(0,n.t)())},3241:(e,t,r)=>{"use strict";r.d(t,{W:()=>o});var n=r(6154);const i="newrelic";function o(e={}){try{n.gm.dispatchEvent(new CustomEvent(i,{detail:e}))}catch(e){}}},1687:(e,t,r)=>{"use strict";r.d(t,{Ak:()=>c,Ze:()=>l,x3:()=>u});var n=r(7836),i=r(3606),o=r(860),a=r(2646);const s={};function c(e,t){const r={staged:!1,priority:o.P3[t]||0};d(e),s[e].get(t)||s[e].set(t,r)}function u(e,t){e&&s[e]&&(s[e].get(t)&&s[e].delete(t),g(e,t,!1),s[e].size&&f(e))}function d(e){if(!e)throw new Error("agentIdentifier required");s[e]||(s[e]=new Map)}function l(e="",t="feature",r=!1){if(d(e),!e||!s[e].get(t)||r)return g(e,t);s[e].get(t).staged=!0,f(e)}function f(e){const t=Array.from(s[e]);t.every((([e,t])=>t.staged))&&(t.sort(((e,t)=>e[1].priority-t[1].priority)),t.forEach((([t])=>{s[e].delete(t),g(e,t)})))}function g(e,t,r=!0){const o=e?n.ee.get(e):n.ee,s=i.i.handlers;if(!o.aborted&&o.backlog&&s){if(r){const e=o.backlog[t],r=s[t];if(r){for(let t=0;e&&t<e.length;++t)p(e[t],r);Object.entries(r).forEach((([e,t])=>{Object.values(t||{}).forEach((t=>{t[0]?.on&&t[0]?.context()instanceof a.y&&t[0].on(e,t[1])}))}))}}o.isolatedBacklog||delete s[t],o.backlog[t]=null,o.emit("drain-"+t,[])}}function p(e,t){var r=e[1];Object.values(t[r]||{}).forEach((t=>{var r=e[0];if(t[0]===r){var n=t[1],i=e[3],o=e[2];n.apply(i,o)}}))}},7836:(e,t,r)=>{"use strict";r.d(t,{P:()=>c,ee:()=>u});var n=r(384),i=r(8990),o=r(3371),a=r(2646),s=r(5607);const c="nr@context:".concat(s.W),u=function e(t,r){var n={},s={},d={},l=!1;try{l=16===r.length&&(0,o.f)(r).isolatedBacklog}catch(e){}var f={on:p,addEventListener:p,removeEventListener:function(e,t){var r=n[e];if(!r)return;for(var i=0;i<r.length;i++)r[i]===t&&r.splice(i,1)},emit:function(e,r,n,i,o){!1!==o&&(o=!0);if(u.aborted&&!i)return;t&&o&&t.emit(e,r,n);for(var a=g(n),c=m(e),d=c.length,l=0;l<d;l++)c[l].apply(a,r);var p=v()[s[e]];p&&p.push([f,e,r,a]);return a},get:h,listeners:m,context:g,buffer:function(e,t){const r=v();if(t=t||"feature",f.aborted)return;Object.entries(e||{}).forEach((([e,n])=>{s[n]=t,t in r||(r[t]=[])}))},abort:function(){f._aborted=!0,Object.keys(f.backlog).forEach((e=>{delete f.backlog[e]}))},isBuffering:function(e){return!!v()[s[e]]},debugId:r,backlog:l?{}:t&&"object"==typeof t.backlog?t.backlog:{},isolatedBacklog:l};return Object.defineProperty(f,"aborted",{get:()=>{let e=f._aborted||!1;return e||(t&&(e=t.aborted),e)}}),f;function g(e){return e&&e instanceof a.y?e:e?(0,i.I)(e,c,(()=>new a.y(c))):new a.y(c)}function p(e,t){n[e]=m(e).concat(t)}function m(e){return n[e]||[]}function h(t){return d[t]=d[t]||e(f,t)}function v(){return f.backlog}}(void 0,"globalEE"),d=(0,n.Zm)();d.ee||(d.ee=u)},2646:(e,t,r)=>{"use strict";r.d(t,{y:()=>n});class n{constructor(e){this.contextId=e}}},9908:(e,t,r)=>{"use strict";r.d(t,{d:()=>n,p:()=>i});var n=r(7836).ee.get("handle");function i(e,t,r,i,o){o?(o.buffer([e],i),o.emit(e,t,r)):(n.buffer([e],i),n.emit(e,t,r))}},3606:(e,t,r)=>{"use strict";r.d(t,{i:()=>o});var n=r(9908);o.on=a;var i=o.handlers={};function o(e,t,r,o){a(o||n.d,i,e,t,r)}function a(e,t,r,i,o){o||(o="feature"),e||(e=n.d);var a=t[o]=t[o]||{};(a[r]=a[r]||[]).push([e,i])}},3878:(e,t,r)=>{"use strict";function n(e,t){return{capture:e,passive:!1,signal:t}}function i(e,t,r=!1,i){window.addEventListener(e,t,n(r,i))}function o(e,t,r=!1,i){document.addEventListener(e,t,n(r,i))}r.d(t,{DD:()=>o,jT:()=>n,sp:()=>i})},5607:(e,t,r)=>{"use strict";r.d(t,{W:()=>n});const n=(0,r(9566).bz)()},9566:(e,t,r)=>{"use strict";r.d(t,{LA:()=>s,bz:()=>a});var n=r(6154);const i="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";function o(e,t){return e?15&e[t]:16*Math.random()|0}function a(){const e=n.gm?.crypto||n.gm?.msCrypto;let t,r=0;return e&&e.getRandomValues&&(t=e.getRandomValues(new Uint8Array(30))),i.split("").map((e=>"x"===e?o(t,r++).toString(16):"y"===e?(3&o()|8).toString(16):e)).join("")}function s(e){const t=n.gm?.crypto||n.gm?.msCrypto;let r,i=0;t&&t.getRandomValues&&(r=t.getRandomValues(new Uint8Array(e)));const a=[];for(var s=0;s<e;s++)a.push(o(r,i++).toString(16));return a.join("")}},2614:(e,t,r)=>{"use strict";r.d(t,{BB:()=>a,H3:()=>n,g:()=>u,iL:()=>c,tS:()=>s,uh:()=>i,wk:()=>o});const n="NRBA",i="SESSION",o=144e5,a=18e5,s={STARTED:"session-started",PAUSE:"session-pause",RESET:"session-reset",RESUME:"session-resume",UPDATE:"session-update"},c={SAME_TAB:"same-tab",CROSS_TAB:"cross-tab"},u={OFF:0,FULL:1,ERROR:2}},1863:(e,t,r)=>{"use strict";function n(){return Math.floor(performance.now())}r.d(t,{t:()=>n})},944:(e,t,r)=>{"use strict";function n(e,t){"function"==typeof console.debug&&console.debug("New Relic Warning: https://github.com/newrelic/newrelic-browser-agent/blob/main/docs/warning-codes.md#".concat(e),t)}r.d(t,{R:()=>n})},5701:(e,t,r)=>{"use strict";r.d(t,{B:()=>a,t:()=>s});var n=r(7836),i=r(3241);const o=new Set,a={};function s(e,t){const r=n.ee.get(t);a[t]??={},e&&"object"==typeof e&&(o.has(t)||(r.emit("rumresp",[e]),a[t]=e,o.add(t),(0,i.W)({agentIdentifier:t,loaded:!0,drained:!0,type:"lifecycle",name:"load",feature:void 0,data:e})))}},8990:(e,t,r)=>{"use strict";r.d(t,{I:()=>i});var n=Object.prototype.hasOwnProperty;function i(e,t,r){if(n.call(e,t))return e[t];var i=r();if(Object.defineProperty&&Object.keys)try{return Object.defineProperty(e,t,{value:i,writable:!0,enumerable:!1}),i}catch(e){}return e[t]=i,i}},6389:(e,t,r)=>{"use strict";function n(e,t=500,r={}){const n=r?.leading||!1;let i;return(...r)=>{n&&void 0===i&&(e.apply(this,r),i=setTimeout((()=>{i=clearTimeout(i)}),t)),n||(clearTimeout(i),i=setTimeout((()=>{e.apply(this,r)}),t))}}function i(e){let t=!1;return(...r)=>{t||(t=!0,e.apply(this,r))}}r.d(t,{J:()=>i,s:()=>n})},5289:(e,t,r)=>{"use strict";r.d(t,{GG:()=>o,sB:()=>a});var n=r(3878);function i(){return"undefined"==typeof document||"complete"===document.readyState}function o(e,t){if(i())return e();(0,n.sp)("load",e,t)}function a(e){if(i())return e();(0,n.DD)("DOMContentLoaded",e)}},384:(e,t,r)=>{"use strict";r.d(t,{NT:()=>o,US:()=>d,Zm:()=>a,bQ:()=>c,dV:()=>s,nY:()=>u,pV:()=>l});var n=r(6154),i=r(1863);const o={beacon:"bam.nr-data.net",errorBeacon:"bam.nr-data.net"};function a(){return n.gm.NREUM||(n.gm.NREUM={}),void 0===n.gm.newrelic&&(n.gm.newrelic=n.gm.NREUM),n.gm.NREUM}function s(){let e=a();return e.o||(e.o={ST:n.gm.setTimeout,SI:n.gm.setImmediate,CT:n.gm.clearTimeout,XHR:n.gm.XMLHttpRequest,REQ:n.gm.Request,EV:n.gm.Event,PR:n.gm.Promise,MO:n.gm.MutationObserver,FETCH:n.gm.fetch,WS:n.gm.WebSocket}),e}function c(e,t){let r=a();r.initializedAgents??={},t.initializedAt={ms:(0,i.t)(),date:new Date},r.initializedAgents[e]=t}function u(e){let t=a();return t.initializedAgents?.[e]}function d(e,t){a()[e]=t}function l(){return function(){let e=a();const t=e.info||{};e.info={beacon:o.beacon,errorBeacon:o.errorBeacon,...t}}(),function(){let e=a();const t=e.init||{};e.init={...t}}(),s(),function(){let e=a();const t=e.loader_config||{};e.loader_config={...t}}(),a()}},2843:(e,t,r)=>{"use strict";r.d(t,{u:()=>i});var n=r(3878);function i(e,t=!1,r,i){(0,n.DD)("visibilitychange",(function(){if(t)return void("hidden"===document.visibilityState&&e());e(document.visibilityState)}),r,i)}},3434:(e,t,r)=>{"use strict";r.d(t,{Jt:()=>o,YM:()=>c});var n=r(7836),i=r(5607);const o="nr@original:".concat(i.W);var a=Object.prototype.hasOwnProperty,s=!1;function c(e,t){return e||(e=n.ee),r.inPlace=function(e,t,n,i,o){n||(n="");const a="-"===n.charAt(0);for(let s=0;s<t.length;s++){const c=t[s],u=e[c];d(u)||(e[c]=r(u,a?c+n:n,i,c,o))}},r.flag=o,r;function r(t,r,n,s,c){return d(t)?t:(r||(r=""),nrWrapper[o]=t,function(e,t,r){if(Object.defineProperty&&Object.keys)try{return Object.keys(e).forEach((function(r){Object.defineProperty(t,r,{get:function(){return e[r]},set:function(t){return e[r]=t,t}})})),t}catch(e){u([e],r)}for(var n in e)a.call(e,n)&&(t[n]=e[n])}(t,nrWrapper,e),nrWrapper);function nrWrapper(){var o,a,d,l;try{a=this,o=[...arguments],d="function"==typeof n?n(o,a):n||{}}catch(t){u([t,"",[o,a,s],d],e)}i(r+"start",[o,a,s],d,c);try{return l=t.apply(a,o)}catch(e){throw i(r+"err",[o,a,e],d,c),e}finally{i(r+"end",[o,a,l],d,c)}}}function i(r,n,i,o){if(!s||t){var a=s;s=!0;try{e.emit(r,n,i,t,o)}catch(t){u([t,r,n,i],e)}s=a}}}function u(e,t){t||(t=n.ee);try{t.emit("internal-error",e)}catch(e){}}function d(e){return!(e&&"function"==typeof e&&e.apply&&!e[o])}},993:(e,t,r)=>{"use strict";r.d(t,{A$:()=>o,ET:()=>a,p_:()=>i});var n=r(860);const i={ERROR:"ERROR",WARN:"WARN",INFO:"INFO",DEBUG:"DEBUG",TRACE:"TRACE"},o={OFF:0,ERROR:1,WARN:2,INFO:3,DEBUG:4,TRACE:5},a="log";n.K7.logging},8154:(e,t,r)=>{"use strict";r.d(t,{z_:()=>o,XG:()=>s,TZ:()=>n,rs:()=>i,xV:()=>a});r(6154),r(9566),r(384);const n=r(860).K7.metrics,i="sm",o="cm",a="storeSupportabilityMetrics",s="storeEventMetrics"},6630:(e,t,r)=>{"use strict";r.d(t,{T:()=>n});const n=r(860).K7.pageViewEvent},782:(e,t,r)=>{"use strict";r.d(t,{T:()=>n});const n=r(860).K7.pageViewTiming},6344:(e,t,r)=>{"use strict";r.d(t,{G4:()=>i});var n=r(2614);r(860).K7.sessionReplay;const i={RECORD:"recordReplay",PAUSE:"pauseReplay",REPLAY_RUNNING:"replayRunning",ERROR_DURING_REPLAY:"errorDuringReplay"};n.g.ERROR,n.g.FULL,n.g.OFF},4234:(e,t,r)=>{"use strict";r.d(t,{W:()=>o});var n=r(7836),i=r(1687);class o{constructor(e,t){this.agentIdentifier=e,this.ee=n.ee.get(e),this.featureName=t,this.blocked=!1}deregisterDrain(){(0,i.x3)(this.agentIdentifier,this.featureName)}}},7603:(e,t,r)=>{"use strict";r.d(t,{j:()=>V});var n=r(860),i=r(2555),o=r(9908),a=r(1687),s=r(5289),c=r(6154),u=r(944),d=r(8154),l=r(384),f=r(6344);const g=["setErrorHandler","finished","addToTrace","addRelease","recordCustomEvent","addPageAction","setCurrentRouteName","setPageViewName","setCustomAttribute","interaction","noticeError","setUserId","setApplicationVersion","start",f.G4.RECORD,f.G4.PAUSE,"log","wrapLogger"],p=["setErrorHandler","finished","addToTrace","addRelease"];var m=r(1863),h=r(2614),v=r(993);var b=r(7836),y=r(2646),w=r(3434);const R=new Map;function A(e,t,r,n){if("object"!=typeof t||!t||"string"!=typeof r||!r||"function"!=typeof t[r])return(0,u.R)(29);const i=function(e){return(e||b.ee).get("logger")}(e),o=(0,w.YM)(i),a=new y.y(b.P);a.level=n.level,a.customAttributes=n.customAttributes;const s=t[r]?.[w.Jt]||t[r];return R.set(s,a),o.inPlace(t,[r],"wrap-logger-",(()=>R.get(s))),i}var E=r(3241),_=r(5701);function x(){const e=(0,l.pV)();g.forEach((t=>{e[t]=(...r)=>function(t,...r){let n=[];return Object.values(e.initializedAgents).forEach((e=>{e&&e.runtime?e.exposed&&e[t]&&"micro-agent"!==e.runtime.loaderType&&n.push(e[t](...r)):(0,u.R)(38,t)})),n[0]}(t,...r)}))}const N={};function I(e,t){t||(0,a.Ak)(e.agentIdentifier,"api");const l=e.ee.get("tracer");N[e.agentIdentifier]=h.g.OFF,e.ee.on(f.G4.REPLAY_RUNNING,(t=>{N[e.agentIdentifier]=t}));const g="api-",b=g+"ixn-";function y(t,r,n,o){const a=e.info;return null===r?delete a.jsAttributes[t]:(0,i.x1)(e.agentIdentifier,{...a,jsAttributes:{...a.jsAttributes,[t]:r}}),x(g,n,!0,o||null===r?"session":void 0)(t,r)}function w(){}e.log=function(t,{customAttributes:r={},level:i=v.p_.INFO}={}){(0,o.p)(d.xV,["API/log/called"],void 0,n.K7.metrics,e.ee),function(e,t,r={},i=v.p_.INFO){(0,o.p)(d.xV,["API/logging/".concat(i.toLowerCase(),"/called")],void 0,n.K7.metrics,e),(0,o.p)(v.ET,[(0,m.t)(),t,r,i],void 0,n.K7.logging,e)}(e.ee,t,r,i)},e.wrapLogger=(t,r,{customAttributes:i={},level:a=v.p_.INFO}={})=>{(0,o.p)(d.xV,["API/wrapLogger/called"],void 0,n.K7.metrics,e.ee),A(e.ee,t,r,{customAttributes:i,level:a})},p.forEach((t=>{e[t]=x(g,t,!0,"api")})),e.addPageAction=x(g,"addPageAction",!0,n.K7.genericEvents),e.recordCustomEvent=x(g,"recordCustomEvent",!0,n.K7.genericEvents),e.setPageViewName=function(t,r){if("string"==typeof t)return"/"!==t.charAt(0)&&(t="/"+t),e.runtime.customTransaction=(r||"http://custom.transaction")+t,x(g,"setPageViewName",!0)()},e.setCustomAttribute=function(e,t,r=!1){if("string"==typeof e){if(["string","number","boolean"].includes(typeof t)||null===t)return y(e,t,"setCustomAttribute",r);(0,u.R)(40,typeof t)}else(0,u.R)(39,typeof e)},e.setUserId=function(e){if("string"==typeof e||null===e)return y("enduser.id",e,"setUserId",!0);(0,u.R)(41,typeof e)},e.setApplicationVersion=function(e){if("string"==typeof e||null===e)return y("application.version",e,"setApplicationVersion",!1);(0,u.R)(42,typeof e)},e.start=()=>{try{(0,o.p)(d.xV,["API/start/called"],void 0,n.K7.metrics,e.ee),e.ee.emit("manual-start-all")}catch(e){(0,u.R)(23,e)}},e[f.G4.RECORD]=function(){(0,o.p)(d.xV,["API/recordReplay/called"],void 0,n.K7.metrics,e.ee),(0,o.p)(f.G4.RECORD,[],void 0,n.K7.sessionReplay,e.ee)},e[f.G4.PAUSE]=function(){(0,o.p)(d.xV,["API/pauseReplay/called"],void 0,n.K7.metrics,e.ee),(0,o.p)(f.G4.PAUSE,[],void 0,n.K7.sessionReplay,e.ee)},e.interaction=function(e){return(new w).get("object"==typeof e?e:{})};const R=w.prototype={createTracer:function(t,r){var i={},a=this,s="function"==typeof r;return(0,o.p)(d.xV,["API/createTracer/called"],void 0,n.K7.metrics,e.ee),e.runSoftNavOverSpa||(0,o.p)(b+"tracer",[(0,m.t)(),t,i],a,n.K7.spa,e.ee),function(){if(l.emit((s?"":"no-")+"fn-start",[(0,m.t)(),a,s],i),s)try{return r.apply(this,arguments)}catch(e){const t="string"==typeof e?new Error(e):e;throw l.emit("fn-err",[arguments,this,t],i),t}finally{l.emit("fn-end",[(0,m.t)()],i)}}}};function x(t,r,i,a){return function(){return(0,o.p)(d.xV,["API/"+r+"/called"],void 0,n.K7.metrics,e.ee),(0,E.W)({agentIdentifier:e.agentIdentifier,drained:!!_.B?.[e.agentIdentifier],type:"data",name:"api",feature:t+r,data:{notSpa:i,bufferGroup:a}}),a&&(0,o.p)(t+r,[i?(0,m.t)():performance.now(),...arguments],i?null:this,a,e.ee),i?void 0:this}}function I(){r.e(296).then(r.bind(r,8778)).then((({setAsyncAPI:t})=>{t(e),(0,a.Ze)(e.agentIdentifier,"api")})).catch((t=>{(0,u.R)(27,t),e.ee.abort()}))}return["actionText","setName","setAttribute","save","ignore","onEnd","getContext","end","get"].forEach((t=>{R[t]=x(b,t,void 0,e.runSoftNavOverSpa?n.K7.softNav:n.K7.spa)})),e.setCurrentRouteName=e.runSoftNavOverSpa?x(b,"routeName",void 0,n.K7.softNav):x(g,"routeName",!0,n.K7.spa),e.noticeError=function(t,r){"string"==typeof t&&(t=new Error(t)),(0,o.p)(d.xV,["API/noticeError/called"],void 0,n.K7.metrics,e.ee),(0,o.p)("err",[t,(0,m.t)(),!1,r,!!N[e.agentIdentifier]],void 0,n.K7.jserrors,e.ee)},c.RI?(0,s.GG)((()=>I()),!0):I(),!0}var k=r(5217),S=r(8122);const T={accountID:void 0,trustKey:void 0,agentID:void 0,licenseKey:void 0,applicationID:void 0,xpid:void 0},O={};var j=r(3371);const P=e=>{const t=e.startsWith("http");e+="/",r.p=t?e:"https://"+e},K=new Set;function V(e,t={},r,n){let{init:o,info:a,loader_config:s,runtime:u={},exposed:d=!0}=t;u.loaderType=r;const f=(0,l.pV)();a||(o=f.init,a=f.info,s=f.loader_config),(0,k.xN)(e.agentIdentifier,o||{}),function(e,t){if(!e)throw new Error("All loader-config objects require an agent identifier!");O[e]=(0,S.a)(t,T);const r=(0,l.nY)(e);r&&(r.loader_config=O[e])}(e.agentIdentifier,s||{}),a.jsAttributes??={},c.bv&&(a.jsAttributes.isWorker=!0),(0,i.x1)(e.agentIdentifier,a);const g=e.init,p=[a.beacon,a.errorBeacon];K.has(e.agentIdentifier)||(g.proxy.assets&&(P(g.proxy.assets),p.push(g.proxy.assets)),g.proxy.beacon&&p.push(g.proxy.beacon),x(),(0,l.US)("activatedFeatures",_.B),e.runSoftNavOverSpa&&=!0===g.soft_navigations.enabled&&g.feature_flags.includes("soft_nav")),u.denyList=[...g.ajax.deny_list||[],...g.ajax.block_internal?p:[]],u.ptid=e.agentIdentifier,(0,j.V)(e.agentIdentifier,u),K.has(e.agentIdentifier)||(e.ee=b.ee.get(e.agentIdentifier),e.exposed=d,I(e,n),(0,E.W)({agentIdentifier:e.agentIdentifier,drained:!!_.B?.[e.agentIdentifier],type:"lifecycle",name:"initialize",feature:void 0,data:e.config})),K.add(e.agentIdentifier)}},8374:(e,t,r)=>{r.nc=(()=>{try{return document?.currentScript?.nonce}catch(e){}return""})()},860:(e,t,r)=>{"use strict";r.d(t,{$J:()=>d,K7:()=>c,P3:()=>u,XX:()=>i,Yy:()=>s,df:()=>o,qY:()=>n,v4:()=>a});const n="events",i="jserrors",o="browser/blobs",a="rum",s="browser/logs",c={ajax:"ajax",genericEvents:"generic_events",jserrors:i,logging:"logging",metrics:"metrics",pageAction:"page_action",pageViewEvent:"page_view_event",pageViewTiming:"page_view_timing",sessionReplay:"session_replay",sessionTrace:"session_trace",softNav:"soft_navigations",spa:"spa"},u={[c.pageViewEvent]:1,[c.pageViewTiming]:2,[c.metrics]:3,[c.jserrors]:4,[c.spa]:5,[c.ajax]:6,[c.sessionTrace]:7,[c.softNav]:8,[c.sessionReplay]:9,[c.logging]:10,[c.genericEvents]:11},d={[c.pageViewEvent]:a,[c.pageViewTiming]:n,[c.ajax]:n,[c.spa]:n,[c.softNav]:n,[c.metrics]:i,[c.jserrors]:i,[c.sessionTrace]:o,[c.sessionReplay]:o,[c.logging]:s,[c.genericEvents]:"ins"}}},n={};function i(e){var t=n[e];if(void 0!==t)return t.exports;var o=n[e]={exports:{}};return r[e](o,o.exports,i),o.exports}i.m=r,i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce(((t,r)=>(i.f[r](e,t),t)),[])),i.u=e=>"nr-rum-1.286.0.min.js",i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),e={},t="NRBA-1.286.0.PROD:",i.l=(r,n,o,a)=>{if(e[r])e[r].push(n);else{var s,c;if(void 0!==o)for(var u=document.getElementsByTagName("script"),d=0;d<u.length;d++){var l=u[d];if(l.getAttribute("src")==r||l.getAttribute("data-webpack")==t+o){s=l;break}}if(!s){c=!0;var f={296:"sha512-+MkNp41sKZ0iYMHsept2X5HfDqyTLnDR9rprfuuxTRn6FVcYOei0L1PleWwmSuU2wrJDnMXcNYjTfSPQ3xYU/w=="};(s=document.createElement("script")).charset="utf-8",s.timeout=120,i.nc&&s.setAttribute("nonce",i.nc),s.setAttribute("data-webpack",t+o),s.src=r,0!==s.src.indexOf(window.location.origin+"/")&&(s.crossOrigin="anonymous"),f[a]&&(s.integrity=f[a])}e[r]=[n];var g=(t,n)=>{s.onerror=s.onload=null,clearTimeout(p);var i=e[r];if(delete e[r],s.parentNode&&s.parentNode.removeChild(s),i&&i.forEach((e=>e(n))),t)return t(n)},p=setTimeout(g.bind(null,void 0,{type:"timeout",target:s}),12e4);s.onerror=g.bind(null,s.onerror),s.onload=g.bind(null,s.onload),c&&document.head.appendChild(s)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.p="https://js-agent.newrelic.com/",(()=>{var e={374:0,840:0};i.f.j=(t,r)=>{var n=i.o(e,t)?e[t]:void 0;if(0!==n)if(n)r.push(n[2]);else{var o=new Promise(((r,i)=>n=e[t]=[r,i]));r.push(n[2]=o);var a=i.p+i.u(t),s=new Error;i.l(a,(r=>{if(i.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var o=r&&("load"===r.type?"missing":r.type),a=r&&r.target&&r.target.src;s.message="Loading chunk "+t+" failed.\n("+o+": "+a+")",s.name="ChunkLoadError",s.type=o,s.request=a,n[1](s)}}),"chunk-"+t,t)}};var t=(t,r)=>{var n,o,[a,s,c]=r,u=0;if(a.some((t=>0!==e[t]))){for(n in s)i.o(s,n)&&(i.m[n]=s[n]);if(c)c(i)}for(t&&t(r);u<a.length;u++)o=a[u],i.o(e,o)&&e[o]&&e[o][0](),e[o]=0},r=self["webpackChunk:NRBA-1.286.0.PROD"]=self["webpackChunk:NRBA-1.286.0.PROD"]||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})(),(()=>{"use strict";i(8374);var e=i(944),t=i(6344),r=i(9566);class n{agentIdentifier;constructor(){this.agentIdentifier=(0,r.LA)(16)}#e(t,...r){if(this[t]!==n.prototype[t])return this[t](...r);(0,e.R)(35,t)}addPageAction(e,t){return this.#e("addPageAction",e,t)}recordCustomEvent(e,t){return this.#e("recordCustomEvent",e,t)}setPageViewName(e,t){return this.#e("setPageViewName",e,t)}setCustomAttribute(e,t,r){return this.#e("setCustomAttribute",e,t,r)}noticeError(e,t){return this.#e("noticeError",e,t)}setUserId(e){return this.#e("setUserId",e)}setApplicationVersion(e){return this.#e("setApplicationVersion",e)}setErrorHandler(e){return this.#e("setErrorHandler",e)}addRelease(e,t){return this.#e("addRelease",e,t)}log(e,t){return this.#e("log",e,t)}}class o extends n{#e(t,...r){if(this[t]!==o.prototype[t]&&this[t]!==n.prototype[t])return this[t](...r);(0,e.R)(35,t)}start(){return this.#e("start")}finished(e){return this.#e("finished",e)}recordReplay(){return this.#e(t.G4.RECORD)}pauseReplay(){return this.#e(t.G4.PAUSE)}addToTrace(e){return this.#e("addToTrace",e)}setCurrentRouteName(e){return this.#e("setCurrentRouteName",e)}interaction(){return this.#e("interaction")}wrapLogger(e,t,r){return this.#e("wrapLogger",e,t,r)}}var a=i(860),s=i(5217);const c=Object.values(a.K7);function u(e){const t={};return c.forEach((r=>{t[r]=function(e,t){return!0===(0,s.gD)(t,"".concat(e,".enabled"))}(r,e)})),t}var d=i(7603);var l=i(1687),f=i(4234),g=i(5289),p=i(6154),m=i(384);const h=e=>p.RI&&!0===(0,s.gD)(e,"privacy.cookies_enabled");function v(e){return!!(0,m.dV)().o.MO&&h(e)&&!0===(0,s.gD)(e,"session_trace.enabled")}var b=i(6389);class y extends f.W{constructor(e,t,r=!0){super(e.agentIdentifier,t),this.auto=r,this.abortHandler=void 0,this.featAggregate=void 0,this.onAggregateImported=void 0,!1===e.init[this.featureName].autoStart&&(this.auto=!1),this.auto?(0,l.Ak)(e.agentIdentifier,t):this.ee.on("manual-start-all",(0,b.J)((()=>{(0,l.Ak)(e.agentIdentifier,this.featureName),this.auto=!0,this.importAggregator(e)})))}importAggregator(t,r={}){if(this.featAggregate||!this.auto)return;let n;this.onAggregateImported=new Promise((e=>{n=e}));const o=async()=>{let o;try{if(h(this.agentIdentifier)){const{setupAgentSession:e}=await i.e(296).then(i.bind(i,3861));o=e(t)}}catch(t){(0,e.R)(20,t),this.ee.emit("internal-error",[t]),this.featureName===a.K7.sessionReplay&&this.abortHandler?.()}try{if(!this.#t(this.featureName,o))return(0,l.Ze)(this.agentIdentifier,this.featureName),void n(!1);const{lazyFeatureLoader:e}=await i.e(296).then(i.bind(i,6103)),{Aggregate:a}=await e(this.featureName,"aggregate");this.featAggregate=new a(t,r),t.runtime.harvester.initializedAggregates.push(this.featAggregate),n(!0)}catch(t){(0,e.R)(34,t),this.abortHandler?.(),(0,l.Ze)(this.agentIdentifier,this.featureName,!0),n(!1),this.ee&&this.ee.abort()}};p.RI?(0,g.GG)((()=>o()),!0):o()}#t(e,t){switch(e){case a.K7.sessionReplay:return v(this.agentIdentifier)&&!!t;case a.K7.sessionTrace:return!!t;default:return!0}}}var w=i(6630);class R extends y{static featureName=w.T;constructor(e,t=!0){super(e,w.T,t),this.importAggregator(e)}}var A=i(9908),E=i(2843),_=i(3878),x=i(782),N=i(1863);class I extends y{static featureName=x.T;constructor(e,t=!0){super(e,x.T,t),p.RI&&((0,E.u)((()=>(0,A.p)("docHidden",[(0,N.t)()],void 0,x.T,this.ee)),!0),(0,_.sp)("pagehide",(()=>(0,A.p)("winPagehide",[(0,N.t)()],void 0,x.T,this.ee))),this.importAggregator(e))}}var k=i(8154);class S extends y{static featureName=k.TZ;constructor(e,t=!0){super(e,k.TZ,t),p.RI&&document.addEventListener("securitypolicyviolation",(e=>{(0,A.p)(k.xV,["Generic/CSPViolation/Detected"],void 0,this.featureName,this.ee)})),this.importAggregator(e)}}new class extends o{constructor(t){super(),p.gm?(this.features={},(0,m.bQ)(this.agentIdentifier,this),this.desiredFeatures=new Set(t.features||[]),this.desiredFeatures.add(R),this.runSoftNavOverSpa=[...this.desiredFeatures].some((e=>e.featureName===a.K7.softNav)),(0,d.j)(this,t,t.loaderType||"agent"),this.run()):(0,e.R)(21)}get config(){return{info:this.info,init:this.init,loader_config:this.loader_config,runtime:this.runtime}}get api(){return this}run(){try{const t=u(this.agentIdentifier),r=[...this.desiredFeatures];r.sort(((e,t)=>a.P3[e.featureName]-a.P3[t.featureName])),r.forEach((r=>{if(!t[r.featureName]&&r.featureName!==a.K7.pageViewEvent)return;if(this.runSoftNavOverSpa&&r.featureName===a.K7.spa)return;if(!this.runSoftNavOverSpa&&r.featureName===a.K7.softNav)return;const n=function(e){switch(e){case a.K7.ajax:return[a.K7.jserrors];case a.K7.sessionTrace:return[a.K7.ajax,a.K7.pageViewEvent];case a.K7.sessionReplay:return[a.K7.sessionTrace];case a.K7.pageViewTiming:return[a.K7.pageViewEvent];default:return[]}}(r.featureName).filter((e=>!(e in this.features)));n.length>0&&(0,e.R)(36,{targetFeature:r.featureName,missingDependencies:n}),this.features[r.featureName]=new r(this)}))}catch(t){(0,e.R)(22,t);for(const e in this.features)this.features[e].abortHandler?.();const r=(0,m.Zm)();delete r.initializedAgents[this.agentIdentifier]?.features,delete this.sharedAggregator;return r.ee.get(this.agentIdentifier).abort(),!1}}}({features:[R,I,S],loaderType:"lite"})})()})();</script><script type="text/javascript">window.NREUM||(NREUM={});NREUM.info={"beacon":"bam.nr-data.net","errorBeacon":"bam.nr-data.net","licenseKey":"NRBR-2fdf56539d4020c5401","applicationID":"957418355","transactionName":"YFYBYEIAXBFTW0NbClkcJUFeAkYLXVYYUQRcRxZHbxZXAEFRQ1dLRVYQW0UTUQdBFkFbAEBAWWBRDVkuW0tDHAJSRw==","queueTime":0,"applicationTime":242,"agent":""}</script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="The latest talks and thought leadership from the Caktus team on Django, UX, Agile, RapidSMS, and more. Delivered locally, nationally, and internationally."> <meta name="author" content=""> <link rel="shortcut icon" type="image/png" href="https://storage.caktusgroup.com/static/images/favicon.1ca0b1cf7100.png"> <link rel="apple-touch-icon" href="https://storage.caktusgroup.com/static/images/favicon-152.a7c8b2b74b4d.png"> <meta property="og:type" content="website" /> <meta name="twitter:card" content="summary" /> <meta property="og:title" content="Web Development Talks | Caktus Group" /> <meta property="og:url" content="https://www.caktusgroup.com/talks/" /> <meta property="og:image" content="https://storage.caktusgroup.com/media/hero_images/colin-pydata.png" /> <meta property="og:description" content="The latest talks and thought leadership from the Caktus team on Django, UX, Agile, RapidSMS, and more. Delivered locally, nationally, and internationally." /> <meta name="twitter:description" content="The latest talks and thought leadership from the Caktus team on Django, UX, Agile, RapidSMS, and more. Delivered locally, nationally, and internationally." /> <meta name="twitter:image" content="https://storage.caktusgroup.com/media/hero_images/colin-pydata.png" /> <title>Web Development Talks | Caktus Group</title> <link rel="stylesheet" type="text/css" media="all" href="https://storage.caktusgroup.com/static/css/bundle.8bf3128f69a3.css"> <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> <![endif]--> <!-- Google Tag Manager --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-TSBBHZR');</script> <!-- End Google Tag Manager --> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-VZFPBRGT04"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-VZFPBRGT04'); </script> <!-- Global site tag (gtag.js) - Google AdWords --> <script async src="https://www.googletagmanager.com/gtag/js?id=AW-1061434655"></script> <script> window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } gtag('js', new Date()); gtag('config', 'AW-1061434655'); </script> <script> !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '702425087568619'); fbq('track', 'PageView'); </script> <noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=702425087568619&ev=PageView&noscript=1" /></noscript> </head> <body id="our-talks" class=""> <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-TSBBHZR" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <!-- Begin Navbar --> <div id="nav" class="navbar" role="navigation"> <div class="wrapper"> <div class="navbar-header"> <button type="button" class="navbar-toggle"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/"> <img src="https://storage.caktusgroup.com/static/images/caktus-logo-426x234.deaf567beb3d.png"/> </a> </div> <nav class="navbar-caktus navbar-off"> <ul class="nav navbar-nav"> <li><a class="service-page" href="/services/">Services <span class="fa"><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="10px" height="10px" viewBox="0 0 284.929 284.929" style="enable-background:new 0 0 284.929 284.929;" xml:space="preserve"> <title>Angle Down</title> <g> <path d="M282.082,76.511l-14.274-14.273c-1.902-1.906-4.093-2.856-6.57-2.856c-2.471,0-4.661,0.95-6.563,2.856L142.466,174.441 L30.262,62.241c-1.903-1.906-4.093-2.856-6.567-2.856c-2.475,0-4.665,0.95-6.567,2.856L2.856,76.515C0.95,78.417,0,80.607,0,83.082 c0,2.473,0.953,4.663,2.856,6.565l133.043,133.046c1.902,1.903,4.093,2.854,6.567,2.854s4.661-0.951,6.562-2.854L282.082,89.647 c1.902-1.903,2.847-4.093,2.847-6.565C284.929,80.607,283.984,78.417,282.082,76.511z"/> </g> </svg> </span></a> <ul> <li><a href="/services/#section-service-types">Service types</a></li> <li><a href="/services/#section-areas-of-expertise">Areas of expertise</a></li> <li><a href="/services/#section-partnerships">Partnerships & Community Involvement</a></li> <li><a href="/services/#section-pricing">Pricing</a></li> </ul> </li> <li><a class="our-work" href="/casestudies/">Our work <span class="fa"><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="10px" height="10px" viewBox="0 0 284.929 284.929" style="enable-background:new 0 0 284.929 284.929;" xml:space="preserve"> <title>Angle Down</title> <g> <path d="M282.082,76.511l-14.274-14.273c-1.902-1.906-4.093-2.856-6.57-2.856c-2.471,0-4.661,0.95-6.563,2.856L142.466,174.441 L30.262,62.241c-1.903-1.906-4.093-2.856-6.567-2.856c-2.475,0-4.665,0.95-6.567,2.856L2.856,76.515C0.95,78.417,0,80.607,0,83.082 c0,2.473,0.953,4.663,2.856,6.565l133.043,133.046c1.902,1.903,4.093,2.854,6.567,2.854s4.661-0.951,6.562-2.854L282.082,89.647 c1.902-1.903,2.847-4.093,2.847-6.565C284.929,80.607,283.984,78.417,282.082,76.511z"/> </g> </svg> </span></a> <ul> <li><a href="/casestudies/#section-case-studies">Case studies</a></li> <li><a href="/casestudies/#section-client-feedback">Client feedback</a></li> </ul> </li> <li><a class="about-us" href="/about/">About us <span class="fa"><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="10px" height="10px" viewBox="0 0 284.929 284.929" style="enable-background:new 0 0 284.929 284.929;" xml:space="preserve"> <title>Angle Down</title> <g> <path d="M282.082,76.511l-14.274-14.273c-1.902-1.906-4.093-2.856-6.57-2.856c-2.471,0-4.661,0.95-6.563,2.856L142.466,174.441 L30.262,62.241c-1.903-1.906-4.093-2.856-6.567-2.856c-2.475,0-4.665,0.95-6.567,2.856L2.856,76.515C0.95,78.417,0,80.607,0,83.082 c0,2.473,0.953,4.663,2.856,6.565l133.043,133.046c1.902,1.903,4.093,2.854,6.567,2.854s4.661-0.951,6.562-2.854L282.082,89.647 c1.902-1.903,2.847-4.093,2.847-6.565C284.929,80.607,283.984,78.417,282.082,76.511z"/> </g> </svg> </span></a> <ul> <li><a href="/about/#section-open-source">Open source</a></li> <li><a href="/about/#section-community-participation">Community engagement</a></li> <li><a href="/about/#section-press">Press</a></li> <li><a href="/ebooks/">Ebooks</a></li> <li><a href="/about/#section-charitable-giving">Charitable giving</a></li> <li><a href="/talks/">Talks &amp; Publications</a></li> <li><a href="/about/#section-our-team">Team</a></li> </ul> </li> <li><a class="careers" href="/careers/">Careers</a></li> <li><a class="posts" href="/blog/">Blog</a></li> <li class="focus"><a class="contact" href="/contact/">Contact</a></li> </ul> </nav> </div> </div><!-- /end Navbar --> <div id="wrap"> <main id="main-content"> <div class="container"> </div> <div class="landing-hero row landing-hero-talks" style="background-image: linear-gradient(rgba(20, 10, 0, .55), rgba(20, 10, 0, .7)), url('https://storage.caktusgroup.com/media/hero_images/colin-pydata.png')"> <div class="wrapper cushion-big-space"> <div class="half white center"> <h1>Talks and Publications</h1> <div class="spacer"></div> <h3> <div>See what our team is saying about web development, design, complex projects, and social impact technology.</div> </h3> </div> </div> </div> <!-- TALKS --> <section class="lt-grey-bg"> <!-- SEARCH / FILTER SORT --> <div class="full row lt-grey-bg white list-view-filter underline-link"> <div class="wrapper"> <div class="topic-categories three-quarters"> <h3> Categories: </h3> <ul> <li> <a class="active-underline" href="/talks/">All</a> </li> <li> <a href="/talks/categories/slideshow/">Slideshow </a> </li> <li> <a href="/talks/categories/video/">Video </a> </li> </ul> </div> <div class="quarter"> <form method="GET" charset="utf-8" action="/talks/search/"> <div class="search-container"> <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Search</title><path d="M1216 832q0-185-131.5-316.5t-316.5-131.5-316.5 131.5-131.5 316.5 131.5 316.5 316.5 131.5 316.5-131.5 131.5-316.5zm512 832q0 52-38 90t-90 38q-54 0-90-38l-343-342q-179 124-399 124-143 0-273.5-55.5t-225-150-150-225-55.5-273.5 55.5-273.5 150-225 225-150 273.5-55.5 273.5 55.5 225 150 150 225 55.5 273.5q0 220-124 399l343 343q37 37 37 90z"/></svg></span> <input type="search" id="search" name="q" value="" placeholder="Search..." /> </div> </form> </div> </div> </div> <!-- POST PREVIEW CARDS --> <!-- The hairline that goes across the top of the page--> <div class="full our-blog lt-grey-bg"> <div class="wrapper search_result_text"> <div class="hairline"></div> <div id="search-message" class="search-message center"> </div> </div> </div> <!-- Div id used for infinite scroll --> <div id="card-page" class="home-page"> <div id="our-blog" class="full our-blog lt-grey-bg"> <div class="wrapper"> <div class="blog-card-wrapper full"> <!-- start-of-card --> <!-- The talk class is used to find the number of cards on the page in the jscroll callback --> <div class="card talk"> <div class="card-work"> <a href="/talks/automated-problem-reporting/"> <img src="https://storage.caktusgroup.com/media/thumbnail-cache/f2/df/f2dfc1217735f4dad30e1e02174ccec5.png" alt="Teach your sites to call for help: automated problem reporting (cover image)"> </a> </div> <div class="card-info"> <div class="label-block full"> <div class="full blue"> <a href="/talks/categories/slideshow/"> <!-- Use the video icon --> <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Play</title><path d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5-103 385.5-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103zm384 823q32-18 32-55t-32-55l-544-320q-31-19-64-1-32 19-32 56v640q0 37 32 56 16 8 32 8 17 0 32-9z"/></svg></span>&ensp; <!-- Talk category name --> Slideshow </a> </div> </div> <div class="title"> <a href="/talks/automated-problem-reporting/"> Teach Your Sites to Call for Help: Automated Problem Reporting for Online Services </a> </div> <div class="label-block full"> <div class="author-green full"> <!-- If the speaker is a Caktus employee, then we link to their user bio page --> Dan Poirier </div> </div> <div class="sample-text"> <p> <a href="/talks/automated-problem-reporting/"> Keep users happy after your site launches by addressing problems before users complain. This presentation by Caktus developer Dan Poirier, delivered at PyTennessee 2018, lays out which problems you may want to be notified about and a number of tools that can help. </a> </p> </div> <div class="spacer"></div> <div class="location blue-grey"> PyTennessee </div> <div class="date-and-social"> <div class="date blue-grey"> February 11, 2018 </div> <div class="social-media-icon-bundle blue-grey"> <div class="card-common--social-media"> <!-- Twitter --> <a target="_blank" href="https://twitter.com/intent/tweet?text=Teach%20Your%20Sites%20to%20Call%20for%20Help%3A%20Automated%20Problem%20Reporting%20for%20Online%20Services&tw_p=tweetbutton&url=https://www.caktusgroup.com/talks/automated-problem-reporting/"><span class="fa"><svg version="1.1" id="svg_twitter" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 449.956 449.956" style="enable-background:new 0 0 449.956 449.956;" xml:space="preserve"> <title>Twitter</title> <g> <path d="M449.956,85.657c-17.702,7.614-35.408,12.369-53.102,14.279c19.985-11.991,33.503-28.931,40.546-50.819 c-18.281,10.847-37.787,18.268-58.532,22.267c-18.274-19.414-40.73-29.125-67.383-29.125c-25.502,0-47.246,8.992-65.24,26.98 c-17.984,17.987-26.977,39.731-26.977,65.235c0,6.851,0.76,13.896,2.284,21.128c-37.688-1.903-73.042-11.372-106.068-28.407 C82.46,110.158,54.433,87.46,31.403,59.101c-8.375,14.272-12.564,29.787-12.564,46.536c0,15.798,3.711,30.456,11.138,43.97 c7.422,13.512,17.417,24.455,29.98,32.831c-14.849-0.572-28.743-4.475-41.684-11.708v1.142c0,22.271,6.995,41.824,20.983,58.674 c13.99,16.848,31.645,27.453,52.961,31.833c-7.995,2.091-16.086,3.138-24.269,3.138c-5.33,0-11.136-0.475-17.416-1.42 c5.9,18.459,16.75,33.633,32.546,45.535c15.799,11.896,33.691,18.028,53.677,18.418c-33.498,26.262-71.66,39.393-114.486,39.393 c-8.186,0-15.607-0.373-22.27-1.139c42.827,27.596,90.03,41.394,141.612,41.394c32.738,0,63.478-5.181,92.21-15.557 c28.746-10.369,53.297-24.267,73.665-41.686c20.362-17.415,37.925-37.448,52.674-60.097c14.75-22.651,25.738-46.298,32.977-70.946 c7.23-24.653,10.848-49.344,10.848-74.092c0-5.33-0.096-9.325-0.287-11.991C421.785,120.202,437.202,104.306,449.956,85.657z"/> </g> </svg> </span></a> &ensp; <!-- LinkedIn --> <a target="_blank" href="https://www.linkedin.com/cws/share?url=https://www.caktusgroup.com/talks/automated-problem-reporting/"><span class="fa"><svg version="1.1" id="svg_linkedin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.536 438.535" style="enable-background:new 0 0 438.536 438.535;" xml:space="preserve"> <title>LinkedIn</title> <g> <g> <rect x="5.424" y="145.895" width="94.216" height="282.932"/> <path d="M408.842,171.739c-19.791-21.604-45.967-32.408-78.512-32.408c-11.991,0-22.891,1.475-32.695,4.427 c-9.801,2.95-18.079,7.089-24.838,12.419c-6.755,5.33-12.135,10.278-16.129,14.844c-3.798,4.337-7.512,9.389-11.136,15.104 v-40.232h-93.935l0.288,13.706c0.193,9.139,0.288,37.307,0.288,84.508c0,47.205-0.19,108.777-0.572,184.722h93.931V270.942 c0-9.705,1.041-17.412,3.139-23.127c4-9.712,10.037-17.843,18.131-24.407c8.093-6.572,18.13-9.855,30.125-9.855 c16.364,0,28.407,5.662,36.117,16.987c7.707,11.324,11.561,26.98,11.561,46.966V428.82h93.931V266.664 C438.529,224.976,428.639,193.336,408.842,171.739z"/> <path d="M53.103,9.708c-15.796,0-28.595,4.619-38.4,13.848C4.899,32.787,0,44.441,0,58.529c0,13.891,4.758,25.505,14.275,34.829 c9.514,9.325,22.078,13.99,37.685,13.99h0.571c15.99,0,28.887-4.661,38.688-13.99c9.801-9.324,14.606-20.934,14.417-34.829 c-0.19-14.087-5.047-25.742-14.561-34.973C81.562,14.323,68.9,9.708,53.103,9.708z"/> </g> </g> </svg> </span></a> &ensp; <!-- Facebook --> <a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://www.caktusgroup.com/talks/automated-problem-reporting/"><span class="fa"><svg version="1.1" id="svg_facebook" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 470.513 470.513" style="enable-background:new 0 0 470.513 470.513;" xml:space="preserve"> <title>Facebook</title> <g> <path d="M271.521,154.17v-40.541c0-6.086,0.28-10.8,0.849-14.13c0.567-3.335,1.857-6.615,3.859-9.853 c1.999-3.236,5.236-5.47,9.706-6.708c4.476-1.24,10.424-1.858,17.85-1.858h40.539V0h-64.809c-37.5,0-64.433,8.897-80.803,26.691 c-16.368,17.798-24.551,44.014-24.551,78.658v48.82h-48.542v81.086h48.539v235.256h97.362V235.256h64.805l8.566-81.086H271.521z"/> </g> </svg> </span></a> </div> </div> </div> </div> </div> <!-- End of card --> <!-- start-of-card --> <!-- The talk class is used to find the number of cards on the page in the jscroll callback --> <div class="card talk"> <div class="card-work"> <a href="/talks/jira-cloud-sketch/"> <img src="https://storage.caktusgroup.com/media/thumbnail-cache/be/0b/be0bdef844858e15d4fc6bdb3579674d.png" alt="JIRA Cloud for Sketch"> </a> </div> <div class="card-info"> <div class="label-block full"> <div class="full blue"> <a href="/talks/categories/slideshow/"> <!-- Use the video icon --> <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Play</title><path d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5-103 385.5-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103zm384 823q32-18 32-55t-32-55l-544-320q-31-19-64-1-32 19-32 56v640q0 37 32 56 16 8 32 8 17 0 32-9z"/></svg></span>&ensp; <!-- Talk category name --> Slideshow </a> </div> </div> <div class="title"> <a href="/talks/jira-cloud-sketch/"> JIRA Cloud for Sketch </a> </div> <div class="label-block full"> <div class="author-green full"> <!-- If the speaker is a Caktus employee, then we link to their user bio page --> Basia Coulter </div> </div> <div class="sample-text"> <p> <a href="/talks/jira-cloud-sketch/"> Learn how JIRA Cloud for Sketch simplifies workflows and saves time for designers. </a> </p> </div> <div class="spacer"></div> <div class="location blue-grey"> ExploreUX </div> <div class="date-and-social"> <div class="date blue-grey"> February 7, 2018 </div> <div class="social-media-icon-bundle blue-grey"> <div class="card-common--social-media"> <!-- Twitter --> <a target="_blank" href="https://twitter.com/intent/tweet?text=JIRA%20Cloud%20for%20Sketch&tw_p=tweetbutton&url=https://www.caktusgroup.com/talks/jira-cloud-sketch/"><span class="fa"><svg version="1.1" id="svg_twitter" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 449.956 449.956" style="enable-background:new 0 0 449.956 449.956;" xml:space="preserve"> <title>Twitter</title> <g> <path d="M449.956,85.657c-17.702,7.614-35.408,12.369-53.102,14.279c19.985-11.991,33.503-28.931,40.546-50.819 c-18.281,10.847-37.787,18.268-58.532,22.267c-18.274-19.414-40.73-29.125-67.383-29.125c-25.502,0-47.246,8.992-65.24,26.98 c-17.984,17.987-26.977,39.731-26.977,65.235c0,6.851,0.76,13.896,2.284,21.128c-37.688-1.903-73.042-11.372-106.068-28.407 C82.46,110.158,54.433,87.46,31.403,59.101c-8.375,14.272-12.564,29.787-12.564,46.536c0,15.798,3.711,30.456,11.138,43.97 c7.422,13.512,17.417,24.455,29.98,32.831c-14.849-0.572-28.743-4.475-41.684-11.708v1.142c0,22.271,6.995,41.824,20.983,58.674 c13.99,16.848,31.645,27.453,52.961,31.833c-7.995,2.091-16.086,3.138-24.269,3.138c-5.33,0-11.136-0.475-17.416-1.42 c5.9,18.459,16.75,33.633,32.546,45.535c15.799,11.896,33.691,18.028,53.677,18.418c-33.498,26.262-71.66,39.393-114.486,39.393 c-8.186,0-15.607-0.373-22.27-1.139c42.827,27.596,90.03,41.394,141.612,41.394c32.738,0,63.478-5.181,92.21-15.557 c28.746-10.369,53.297-24.267,73.665-41.686c20.362-17.415,37.925-37.448,52.674-60.097c14.75-22.651,25.738-46.298,32.977-70.946 c7.23-24.653,10.848-49.344,10.848-74.092c0-5.33-0.096-9.325-0.287-11.991C421.785,120.202,437.202,104.306,449.956,85.657z"/> </g> </svg> </span></a> &ensp; <!-- LinkedIn --> <a target="_blank" href="https://www.linkedin.com/cws/share?url=https://www.caktusgroup.com/talks/jira-cloud-sketch/"><span class="fa"><svg version="1.1" id="svg_linkedin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.536 438.535" style="enable-background:new 0 0 438.536 438.535;" xml:space="preserve"> <title>LinkedIn</title> <g> <g> <rect x="5.424" y="145.895" width="94.216" height="282.932"/> <path d="M408.842,171.739c-19.791-21.604-45.967-32.408-78.512-32.408c-11.991,0-22.891,1.475-32.695,4.427 c-9.801,2.95-18.079,7.089-24.838,12.419c-6.755,5.33-12.135,10.278-16.129,14.844c-3.798,4.337-7.512,9.389-11.136,15.104 v-40.232h-93.935l0.288,13.706c0.193,9.139,0.288,37.307,0.288,84.508c0,47.205-0.19,108.777-0.572,184.722h93.931V270.942 c0-9.705,1.041-17.412,3.139-23.127c4-9.712,10.037-17.843,18.131-24.407c8.093-6.572,18.13-9.855,30.125-9.855 c16.364,0,28.407,5.662,36.117,16.987c7.707,11.324,11.561,26.98,11.561,46.966V428.82h93.931V266.664 C438.529,224.976,428.639,193.336,408.842,171.739z"/> <path d="M53.103,9.708c-15.796,0-28.595,4.619-38.4,13.848C4.899,32.787,0,44.441,0,58.529c0,13.891,4.758,25.505,14.275,34.829 c9.514,9.325,22.078,13.99,37.685,13.99h0.571c15.99,0,28.887-4.661,38.688-13.99c9.801-9.324,14.606-20.934,14.417-34.829 c-0.19-14.087-5.047-25.742-14.561-34.973C81.562,14.323,68.9,9.708,53.103,9.708z"/> </g> </g> </svg> </span></a> &ensp; <!-- Facebook --> <a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://www.caktusgroup.com/talks/jira-cloud-sketch/"><span class="fa"><svg version="1.1" id="svg_facebook" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 470.513 470.513" style="enable-background:new 0 0 470.513 470.513;" xml:space="preserve"> <title>Facebook</title> <g> <path d="M271.521,154.17v-40.541c0-6.086,0.28-10.8,0.849-14.13c0.567-3.335,1.857-6.615,3.859-9.853 c1.999-3.236,5.236-5.47,9.706-6.708c4.476-1.24,10.424-1.858,17.85-1.858h40.539V0h-64.809c-37.5,0-64.433,8.897-80.803,26.691 c-16.368,17.798-24.551,44.014-24.551,78.658v48.82h-48.542v81.086h48.539v235.256h97.362V235.256h64.805l8.566-81.086H271.521z"/> </g> </svg> </span></a> </div> </div> </div> </div> </div> <!-- End of card --> <!-- start-of-card --> <!-- The talk class is used to find the number of cards on the page in the jscroll callback --> <div class="card talk"> <div class="card-work"> <a href="/talks/write-api-almost-anything-amazing-power-and-flexibility-django-rest-framework/"> <img src="https://storage.caktusgroup.com/media/thumbnail-cache/d2/94/d29466fe10934e126b67502a84ea88fd.png" alt="Cover slide for the presentation, &quot;Write an API for Almost Anything&quot;."> </a> </div> <div class="card-info"> <div class="label-block full"> <div class="full blue"> <a href="/talks/categories/slideshow/"> <!-- Use the video icon --> <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Play</title><path d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5-103 385.5-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103zm384 823q32-18 32-55t-32-55l-544-320q-31-19-64-1-32 19-32 56v640q0 37 32 56 16 8 32 8 17 0 32-9z"/></svg></span>&ensp; <!-- Talk category name --> Slideshow </a> </div> </div> <div class="title"> <a href="/talks/write-api-almost-anything-amazing-power-and-flexibility-django-rest-framework/"> Write an API for Almost Anything: The Amazing Power and Flexibility of Django Rest Framework </a> </div> <div class="label-block full"> <div class="author-green full"> <!-- If the speaker is a Caktus employee, then we link to their user bio page --> Charlotte Mays </div> </div> <div class="sample-text"> <p> <a href="/talks/write-api-almost-anything-amazing-power-and-flexibility-django-rest-framework/"> This presentation dives into what an API is, why they&#39;re useful, and how to build one of your own using the Django Rest Framework. Originally delivered by Caktus developer Charlotte Mays at DjangoCon 2017. </a> </p> </div> <div class="spacer"></div> <div class="location blue-grey"> DjangoCon </div> <div class="date-and-social"> <div class="date blue-grey"> August 14, 2017 </div> <div class="social-media-icon-bundle blue-grey"> <div class="card-common--social-media"> <!-- Twitter --> <a target="_blank" href="https://twitter.com/intent/tweet?text=Write%20an%20API%20for%20Almost%20Anything%3A%20The%20Amazing%20Power%20and%20Flexibility%20of%20Django%20Rest%20Framework&tw_p=tweetbutton&url=https://www.caktusgroup.com/talks/write-api-almost-anything-amazing-power-and-flexibility-django-rest-framework/"><span class="fa"><svg version="1.1" id="svg_twitter" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 449.956 449.956" style="enable-background:new 0 0 449.956 449.956;" xml:space="preserve"> <title>Twitter</title> <g> <path d="M449.956,85.657c-17.702,7.614-35.408,12.369-53.102,14.279c19.985-11.991,33.503-28.931,40.546-50.819 c-18.281,10.847-37.787,18.268-58.532,22.267c-18.274-19.414-40.73-29.125-67.383-29.125c-25.502,0-47.246,8.992-65.24,26.98 c-17.984,17.987-26.977,39.731-26.977,65.235c0,6.851,0.76,13.896,2.284,21.128c-37.688-1.903-73.042-11.372-106.068-28.407 C82.46,110.158,54.433,87.46,31.403,59.101c-8.375,14.272-12.564,29.787-12.564,46.536c0,15.798,3.711,30.456,11.138,43.97 c7.422,13.512,17.417,24.455,29.98,32.831c-14.849-0.572-28.743-4.475-41.684-11.708v1.142c0,22.271,6.995,41.824,20.983,58.674 c13.99,16.848,31.645,27.453,52.961,31.833c-7.995,2.091-16.086,3.138-24.269,3.138c-5.33,0-11.136-0.475-17.416-1.42 c5.9,18.459,16.75,33.633,32.546,45.535c15.799,11.896,33.691,18.028,53.677,18.418c-33.498,26.262-71.66,39.393-114.486,39.393 c-8.186,0-15.607-0.373-22.27-1.139c42.827,27.596,90.03,41.394,141.612,41.394c32.738,0,63.478-5.181,92.21-15.557 c28.746-10.369,53.297-24.267,73.665-41.686c20.362-17.415,37.925-37.448,52.674-60.097c14.75-22.651,25.738-46.298,32.977-70.946 c7.23-24.653,10.848-49.344,10.848-74.092c0-5.33-0.096-9.325-0.287-11.991C421.785,120.202,437.202,104.306,449.956,85.657z"/> </g> </svg> </span></a> &ensp; <!-- LinkedIn --> <a target="_blank" href="https://www.linkedin.com/cws/share?url=https://www.caktusgroup.com/talks/write-api-almost-anything-amazing-power-and-flexibility-django-rest-framework/"><span class="fa"><svg version="1.1" id="svg_linkedin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.536 438.535" style="enable-background:new 0 0 438.536 438.535;" xml:space="preserve"> <title>LinkedIn</title> <g> <g> <rect x="5.424" y="145.895" width="94.216" height="282.932"/> <path d="M408.842,171.739c-19.791-21.604-45.967-32.408-78.512-32.408c-11.991,0-22.891,1.475-32.695,4.427 c-9.801,2.95-18.079,7.089-24.838,12.419c-6.755,5.33-12.135,10.278-16.129,14.844c-3.798,4.337-7.512,9.389-11.136,15.104 v-40.232h-93.935l0.288,13.706c0.193,9.139,0.288,37.307,0.288,84.508c0,47.205-0.19,108.777-0.572,184.722h93.931V270.942 c0-9.705,1.041-17.412,3.139-23.127c4-9.712,10.037-17.843,18.131-24.407c8.093-6.572,18.13-9.855,30.125-9.855 c16.364,0,28.407,5.662,36.117,16.987c7.707,11.324,11.561,26.98,11.561,46.966V428.82h93.931V266.664 C438.529,224.976,428.639,193.336,408.842,171.739z"/> <path d="M53.103,9.708c-15.796,0-28.595,4.619-38.4,13.848C4.899,32.787,0,44.441,0,58.529c0,13.891,4.758,25.505,14.275,34.829 c9.514,9.325,22.078,13.99,37.685,13.99h0.571c15.99,0,28.887-4.661,38.688-13.99c9.801-9.324,14.606-20.934,14.417-34.829 c-0.19-14.087-5.047-25.742-14.561-34.973C81.562,14.323,68.9,9.708,53.103,9.708z"/> </g> </g> </svg> </span></a> &ensp; <!-- Facebook --> <a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://www.caktusgroup.com/talks/write-api-almost-anything-amazing-power-and-flexibility-django-rest-framework/"><span class="fa"><svg version="1.1" id="svg_facebook" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 470.513 470.513" style="enable-background:new 0 0 470.513 470.513;" xml:space="preserve"> <title>Facebook</title> <g> <path d="M271.521,154.17v-40.541c0-6.086,0.28-10.8,0.849-14.13c0.567-3.335,1.857-6.615,3.859-9.853 c1.999-3.236,5.236-5.47,9.706-6.708c4.476-1.24,10.424-1.858,17.85-1.858h40.539V0h-64.809c-37.5,0-64.433,8.897-80.803,26.691 c-16.368,17.798-24.551,44.014-24.551,78.658v48.82h-48.542v81.086h48.539v235.256h97.362V235.256h64.805l8.566-81.086H271.521z"/> </g> </svg> </span></a> </div> </div> </div> </div> </div> <!-- End of card --> </div> <div class="blog-card-wrapper full"> <!-- start-of-card --> <!-- The talk class is used to find the number of cards on the page in the jscroll callback --> <div class="card talk"> <div class="card-work"> <a href="/talks/write-api-almost-anything-video/"> <img src="https://storage.caktusgroup.com/media/thumbnail-cache/41/dc/41dcf7fa98d21cdb2a8a8f0105dfd8b7.png" alt="Charlotte Mays presenting her talk at DjangoCon 2017."> </a> </div> <div class="card-info"> <div class="label-block full"> <div class="full blue"> <a href="/talks/categories/video/"> <!-- Use the video icon --> <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Play</title><path d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5-103 385.5-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103zm384 823q32-18 32-55t-32-55l-544-320q-31-19-64-1-32 19-32 56v640q0 37 32 56 16 8 32 8 17 0 32-9z"/></svg></span>&ensp; <!-- Or the slideshow icon --> <!-- Talk category name --> Video </a> </div> </div> <div class="title"> <a href="/talks/write-api-almost-anything-video/"> Write an API for Almost Anything: The Amazing Power and Flexibility of Django Rest Framework (Video) </a> </div> <div class="label-block full"> <div class="author-green full"> <!-- If the speaker is a Caktus employee, then we link to their user bio page --> Charlotte Mays </div> </div> <div class="sample-text"> <p> <a href="/talks/write-api-almost-anything-video/"> Learn more about what an API is, why they&#39;re useful, and how to build one of your own using the Django Rest Framework. Originally delivered and recorded at DjangoCon 2017. </a> </p> </div> <div class="spacer"></div> <div class="location blue-grey"> DjangoCon </div> <div class="date-and-social"> <div class="date blue-grey"> August 14, 2017 </div> <div class="social-media-icon-bundle blue-grey"> <div class="card-common--social-media"> <!-- Twitter --> <a target="_blank" href="https://twitter.com/intent/tweet?text=Write%20an%20API%20for%20Almost%20Anything%3A%20The%20Amazing%20Power%20and%20Flexibility%20of%20Django%20Rest%20Framework%20%28Video%29&tw_p=tweetbutton&url=https://www.caktusgroup.com/talks/write-api-almost-anything-video/"><span class="fa"><svg version="1.1" id="svg_twitter" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 449.956 449.956" style="enable-background:new 0 0 449.956 449.956;" xml:space="preserve"> <title>Twitter</title> <g> <path d="M449.956,85.657c-17.702,7.614-35.408,12.369-53.102,14.279c19.985-11.991,33.503-28.931,40.546-50.819 c-18.281,10.847-37.787,18.268-58.532,22.267c-18.274-19.414-40.73-29.125-67.383-29.125c-25.502,0-47.246,8.992-65.24,26.98 c-17.984,17.987-26.977,39.731-26.977,65.235c0,6.851,0.76,13.896,2.284,21.128c-37.688-1.903-73.042-11.372-106.068-28.407 C82.46,110.158,54.433,87.46,31.403,59.101c-8.375,14.272-12.564,29.787-12.564,46.536c0,15.798,3.711,30.456,11.138,43.97 c7.422,13.512,17.417,24.455,29.98,32.831c-14.849-0.572-28.743-4.475-41.684-11.708v1.142c0,22.271,6.995,41.824,20.983,58.674 c13.99,16.848,31.645,27.453,52.961,31.833c-7.995,2.091-16.086,3.138-24.269,3.138c-5.33,0-11.136-0.475-17.416-1.42 c5.9,18.459,16.75,33.633,32.546,45.535c15.799,11.896,33.691,18.028,53.677,18.418c-33.498,26.262-71.66,39.393-114.486,39.393 c-8.186,0-15.607-0.373-22.27-1.139c42.827,27.596,90.03,41.394,141.612,41.394c32.738,0,63.478-5.181,92.21-15.557 c28.746-10.369,53.297-24.267,73.665-41.686c20.362-17.415,37.925-37.448,52.674-60.097c14.75-22.651,25.738-46.298,32.977-70.946 c7.23-24.653,10.848-49.344,10.848-74.092c0-5.33-0.096-9.325-0.287-11.991C421.785,120.202,437.202,104.306,449.956,85.657z"/> </g> </svg> </span></a> &ensp; <!-- LinkedIn --> <a target="_blank" href="https://www.linkedin.com/cws/share?url=https://www.caktusgroup.com/talks/write-api-almost-anything-video/"><span class="fa"><svg version="1.1" id="svg_linkedin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.536 438.535" style="enable-background:new 0 0 438.536 438.535;" xml:space="preserve"> <title>LinkedIn</title> <g> <g> <rect x="5.424" y="145.895" width="94.216" height="282.932"/> <path d="M408.842,171.739c-19.791-21.604-45.967-32.408-78.512-32.408c-11.991,0-22.891,1.475-32.695,4.427 c-9.801,2.95-18.079,7.089-24.838,12.419c-6.755,5.33-12.135,10.278-16.129,14.844c-3.798,4.337-7.512,9.389-11.136,15.104 v-40.232h-93.935l0.288,13.706c0.193,9.139,0.288,37.307,0.288,84.508c0,47.205-0.19,108.777-0.572,184.722h93.931V270.942 c0-9.705,1.041-17.412,3.139-23.127c4-9.712,10.037-17.843,18.131-24.407c8.093-6.572,18.13-9.855,30.125-9.855 c16.364,0,28.407,5.662,36.117,16.987c7.707,11.324,11.561,26.98,11.561,46.966V428.82h93.931V266.664 C438.529,224.976,428.639,193.336,408.842,171.739z"/> <path d="M53.103,9.708c-15.796,0-28.595,4.619-38.4,13.848C4.899,32.787,0,44.441,0,58.529c0,13.891,4.758,25.505,14.275,34.829 c9.514,9.325,22.078,13.99,37.685,13.99h0.571c15.99,0,28.887-4.661,38.688-13.99c9.801-9.324,14.606-20.934,14.417-34.829 c-0.19-14.087-5.047-25.742-14.561-34.973C81.562,14.323,68.9,9.708,53.103,9.708z"/> </g> </g> </svg> </span></a> &ensp; <!-- Facebook --> <a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://www.caktusgroup.com/talks/write-api-almost-anything-video/"><span class="fa"><svg version="1.1" id="svg_facebook" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 470.513 470.513" style="enable-background:new 0 0 470.513 470.513;" xml:space="preserve"> <title>Facebook</title> <g> <path d="M271.521,154.17v-40.541c0-6.086,0.28-10.8,0.849-14.13c0.567-3.335,1.857-6.615,3.859-9.853 c1.999-3.236,5.236-5.47,9.706-6.708c4.476-1.24,10.424-1.858,17.85-1.858h40.539V0h-64.809c-37.5,0-64.433,8.897-80.803,26.691 c-16.368,17.798-24.551,44.014-24.551,78.658v48.82h-48.542v81.086h48.539v235.256h97.362V235.256h64.805l8.566-81.086H271.521z"/> </g> </svg> </span></a> </div> </div> </div> </div> </div> <!-- End of card --> <!-- start-of-card --> <!-- The talk class is used to find the number of cards on the page in the jscroll callback --> <div class="card talk"> <div class="card-work"> <a href="/talks/caktus-group-lightning-talk-user-story-mapping-release-plan/"> <img src="https://storage.caktusgroup.com/media/thumbnail-cache/96/9e/969e1d8162db80892a660d7b2b6ac3d1.png" alt="Cover slide for Basia Coulter&#39;s talk about using user story mapping to develop a high-level release plan."> </a> </div> <div class="card-info"> <div class="label-block full"> <div class="full blue"> <a href="/talks/categories/slideshow/"> <!-- Use the video icon --> <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Play</title><path d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5-103 385.5-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103zm384 823q32-18 32-55t-32-55l-544-320q-31-19-64-1-32 19-32 56v640q0 37 32 56 16 8 32 8 17 0 32-9z"/></svg></span>&ensp; <!-- Talk category name --> Slideshow </a> </div> </div> <div class="title"> <a href="/talks/caktus-group-lightning-talk-user-story-mapping-release-plan/"> Caktus Group Lightning Talk: From User Story Mapping to Release Plan </a> </div> <div class="label-block full"> <div class="author-green full"> <!-- If the speaker is a Caktus employee, then we link to their user bio page --> Basia Coulter </div> </div> <div class="sample-text"> <p> <a href="/talks/caktus-group-lightning-talk-user-story-mapping-release-plan/"> UX Designer Basia Coulter delivered a lightning talk at Caktus about user story mapping and how to use it to deliver a high-level release plan for web development. This talk was also delivered as part of the ExploreUX Raleigh Meetup&#39;s lightning talk series. </a> </p> </div> <div class="spacer"></div> <div class="location blue-grey"> </div> <div class="date-and-social"> <div class="date blue-grey"> June 22, 2017 </div> <div class="social-media-icon-bundle blue-grey"> <div class="card-common--social-media"> <!-- Twitter --> <a target="_blank" href="https://twitter.com/intent/tweet?text=Caktus%20Group%20Lightning%20Talk%3A%20From%20User%20Story%20Mapping%20to%20Release%20Plan&tw_p=tweetbutton&url=https://www.caktusgroup.com/talks/caktus-group-lightning-talk-user-story-mapping-release-plan/"><span class="fa"><svg version="1.1" id="svg_twitter" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 449.956 449.956" style="enable-background:new 0 0 449.956 449.956;" xml:space="preserve"> <title>Twitter</title> <g> <path d="M449.956,85.657c-17.702,7.614-35.408,12.369-53.102,14.279c19.985-11.991,33.503-28.931,40.546-50.819 c-18.281,10.847-37.787,18.268-58.532,22.267c-18.274-19.414-40.73-29.125-67.383-29.125c-25.502,0-47.246,8.992-65.24,26.98 c-17.984,17.987-26.977,39.731-26.977,65.235c0,6.851,0.76,13.896,2.284,21.128c-37.688-1.903-73.042-11.372-106.068-28.407 C82.46,110.158,54.433,87.46,31.403,59.101c-8.375,14.272-12.564,29.787-12.564,46.536c0,15.798,3.711,30.456,11.138,43.97 c7.422,13.512,17.417,24.455,29.98,32.831c-14.849-0.572-28.743-4.475-41.684-11.708v1.142c0,22.271,6.995,41.824,20.983,58.674 c13.99,16.848,31.645,27.453,52.961,31.833c-7.995,2.091-16.086,3.138-24.269,3.138c-5.33,0-11.136-0.475-17.416-1.42 c5.9,18.459,16.75,33.633,32.546,45.535c15.799,11.896,33.691,18.028,53.677,18.418c-33.498,26.262-71.66,39.393-114.486,39.393 c-8.186,0-15.607-0.373-22.27-1.139c42.827,27.596,90.03,41.394,141.612,41.394c32.738,0,63.478-5.181,92.21-15.557 c28.746-10.369,53.297-24.267,73.665-41.686c20.362-17.415,37.925-37.448,52.674-60.097c14.75-22.651,25.738-46.298,32.977-70.946 c7.23-24.653,10.848-49.344,10.848-74.092c0-5.33-0.096-9.325-0.287-11.991C421.785,120.202,437.202,104.306,449.956,85.657z"/> </g> </svg> </span></a> &ensp; <!-- LinkedIn --> <a target="_blank" href="https://www.linkedin.com/cws/share?url=https://www.caktusgroup.com/talks/caktus-group-lightning-talk-user-story-mapping-release-plan/"><span class="fa"><svg version="1.1" id="svg_linkedin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.536 438.535" style="enable-background:new 0 0 438.536 438.535;" xml:space="preserve"> <title>LinkedIn</title> <g> <g> <rect x="5.424" y="145.895" width="94.216" height="282.932"/> <path d="M408.842,171.739c-19.791-21.604-45.967-32.408-78.512-32.408c-11.991,0-22.891,1.475-32.695,4.427 c-9.801,2.95-18.079,7.089-24.838,12.419c-6.755,5.33-12.135,10.278-16.129,14.844c-3.798,4.337-7.512,9.389-11.136,15.104 v-40.232h-93.935l0.288,13.706c0.193,9.139,0.288,37.307,0.288,84.508c0,47.205-0.19,108.777-0.572,184.722h93.931V270.942 c0-9.705,1.041-17.412,3.139-23.127c4-9.712,10.037-17.843,18.131-24.407c8.093-6.572,18.13-9.855,30.125-9.855 c16.364,0,28.407,5.662,36.117,16.987c7.707,11.324,11.561,26.98,11.561,46.966V428.82h93.931V266.664 C438.529,224.976,428.639,193.336,408.842,171.739z"/> <path d="M53.103,9.708c-15.796,0-28.595,4.619-38.4,13.848C4.899,32.787,0,44.441,0,58.529c0,13.891,4.758,25.505,14.275,34.829 c9.514,9.325,22.078,13.99,37.685,13.99h0.571c15.99,0,28.887-4.661,38.688-13.99c9.801-9.324,14.606-20.934,14.417-34.829 c-0.19-14.087-5.047-25.742-14.561-34.973C81.562,14.323,68.9,9.708,53.103,9.708z"/> </g> </g> </svg> </span></a> &ensp; <!-- Facebook --> <a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://www.caktusgroup.com/talks/caktus-group-lightning-talk-user-story-mapping-release-plan/"><span class="fa"><svg version="1.1" id="svg_facebook" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 470.513 470.513" style="enable-background:new 0 0 470.513 470.513;" xml:space="preserve"> <title>Facebook</title> <g> <path d="M271.521,154.17v-40.541c0-6.086,0.28-10.8,0.849-14.13c0.567-3.335,1.857-6.615,3.859-9.853 c1.999-3.236,5.236-5.47,9.706-6.708c4.476-1.24,10.424-1.858,17.85-1.858h40.539V0h-64.809c-37.5,0-64.433,8.897-80.803,26.691 c-16.368,17.798-24.551,44.014-24.551,78.658v48.82h-48.542v81.086h48.539v235.256h97.362V235.256h64.805l8.566-81.086H271.521z"/> </g> </svg> </span></a> </div> </div> </div> </div> </div> <!-- End of card --> <!-- start-of-card --> <!-- The talk class is used to find the number of cards on the page in the jscroll callback --> <div class="card talk"> <div class="card-work"> <a href="/talks/setting-jupyterhub-distance-learning/"> <img src="https://storage.caktusgroup.com/media/thumbnail-cache/e7/61/e76145d53c8a1b94630c2d600640b8a5.png" alt="Setting up JupyterHub for Distance Learning"> </a> </div> <div class="card-info"> <div class="label-block full"> <div class="full blue"> <a href="/talks/categories/video/"> <!-- Use the video icon --> <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Play</title><path d="M896 128q209 0 385.5 103t279.5 279.5 103 385.5-103 385.5-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103zm384 823q32-18 32-55t-32-55l-544-320q-31-19-64-1-32 19-32 56v640q0 37 32 56 16 8 32 8 17 0 32-9z"/></svg></span>&ensp; <!-- Or the slideshow icon --> <!-- Talk category name --> Video </a> </div> </div> <div class="title"> <a href="/talks/setting-jupyterhub-distance-learning/"> Setting Up JupyterHub for Distance Learning </a> </div> <div class="label-block full"> <div class="author-green full"> <!-- If the speaker is a Caktus employee, then we link to their user bio page --> Charlotte Mays </div> </div> <div class="sample-text"> <p> <a href="/talks/setting-jupyterhub-distance-learning/"> This talk demonstrates setting up a JupyterHub on Digital Ocean Webhosting for a distance learning tutorial. One of the challenges of distance learning is configuring student computers with a uniform Python development system, a situation which is compounded with remote students. As part of the solution, Charlotte utilizes a repo authored by Min Ragan Kelley, whom she acknowledges with gratitude and respect. She also includes an explanation of the use of letsencrypt. Charlotte is a principle facilitator in the local PyLadies chapter and intends to use this tutorial as part of her involvement with teaching intro-level Python classes. </a> </p> </div> <div class="spacer"></div> <div class="location blue-grey"> TriPython </div> <div class="date-and-social"> <div class="date blue-grey"> March 23, 2017 </div> <div class="social-media-icon-bundle blue-grey"> <div class="card-common--social-media"> <!-- Twitter --> <a target="_blank" href="https://twitter.com/intent/tweet?text=Setting%20Up%20JupyterHub%20for%20Distance%20Learning&tw_p=tweetbutton&url=https://www.caktusgroup.com/talks/setting-jupyterhub-distance-learning/"><span class="fa"><svg version="1.1" id="svg_twitter" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 449.956 449.956" style="enable-background:new 0 0 449.956 449.956;" xml:space="preserve"> <title>Twitter</title> <g> <path d="M449.956,85.657c-17.702,7.614-35.408,12.369-53.102,14.279c19.985-11.991,33.503-28.931,40.546-50.819 c-18.281,10.847-37.787,18.268-58.532,22.267c-18.274-19.414-40.73-29.125-67.383-29.125c-25.502,0-47.246,8.992-65.24,26.98 c-17.984,17.987-26.977,39.731-26.977,65.235c0,6.851,0.76,13.896,2.284,21.128c-37.688-1.903-73.042-11.372-106.068-28.407 C82.46,110.158,54.433,87.46,31.403,59.101c-8.375,14.272-12.564,29.787-12.564,46.536c0,15.798,3.711,30.456,11.138,43.97 c7.422,13.512,17.417,24.455,29.98,32.831c-14.849-0.572-28.743-4.475-41.684-11.708v1.142c0,22.271,6.995,41.824,20.983,58.674 c13.99,16.848,31.645,27.453,52.961,31.833c-7.995,2.091-16.086,3.138-24.269,3.138c-5.33,0-11.136-0.475-17.416-1.42 c5.9,18.459,16.75,33.633,32.546,45.535c15.799,11.896,33.691,18.028,53.677,18.418c-33.498,26.262-71.66,39.393-114.486,39.393 c-8.186,0-15.607-0.373-22.27-1.139c42.827,27.596,90.03,41.394,141.612,41.394c32.738,0,63.478-5.181,92.21-15.557 c28.746-10.369,53.297-24.267,73.665-41.686c20.362-17.415,37.925-37.448,52.674-60.097c14.75-22.651,25.738-46.298,32.977-70.946 c7.23-24.653,10.848-49.344,10.848-74.092c0-5.33-0.096-9.325-0.287-11.991C421.785,120.202,437.202,104.306,449.956,85.657z"/> </g> </svg> </span></a> &ensp; <!-- LinkedIn --> <a target="_blank" href="https://www.linkedin.com/cws/share?url=https://www.caktusgroup.com/talks/setting-jupyterhub-distance-learning/"><span class="fa"><svg version="1.1" id="svg_linkedin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.536 438.535" style="enable-background:new 0 0 438.536 438.535;" xml:space="preserve"> <title>LinkedIn</title> <g> <g> <rect x="5.424" y="145.895" width="94.216" height="282.932"/> <path d="M408.842,171.739c-19.791-21.604-45.967-32.408-78.512-32.408c-11.991,0-22.891,1.475-32.695,4.427 c-9.801,2.95-18.079,7.089-24.838,12.419c-6.755,5.33-12.135,10.278-16.129,14.844c-3.798,4.337-7.512,9.389-11.136,15.104 v-40.232h-93.935l0.288,13.706c0.193,9.139,0.288,37.307,0.288,84.508c0,47.205-0.19,108.777-0.572,184.722h93.931V270.942 c0-9.705,1.041-17.412,3.139-23.127c4-9.712,10.037-17.843,18.131-24.407c8.093-6.572,18.13-9.855,30.125-9.855 c16.364,0,28.407,5.662,36.117,16.987c7.707,11.324,11.561,26.98,11.561,46.966V428.82h93.931V266.664 C438.529,224.976,428.639,193.336,408.842,171.739z"/> <path d="M53.103,9.708c-15.796,0-28.595,4.619-38.4,13.848C4.899,32.787,0,44.441,0,58.529c0,13.891,4.758,25.505,14.275,34.829 c9.514,9.325,22.078,13.99,37.685,13.99h0.571c15.99,0,28.887-4.661,38.688-13.99c9.801-9.324,14.606-20.934,14.417-34.829 c-0.19-14.087-5.047-25.742-14.561-34.973C81.562,14.323,68.9,9.708,53.103,9.708z"/> </g> </g> </svg> </span></a> &ensp; <!-- Facebook --> <a target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://www.caktusgroup.com/talks/setting-jupyterhub-distance-learning/"><span class="fa"><svg version="1.1" id="svg_facebook" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 470.513 470.513" style="enable-background:new 0 0 470.513 470.513;" xml:space="preserve"> <title>Facebook</title> <g> <path d="M271.521,154.17v-40.541c0-6.086,0.28-10.8,0.849-14.13c0.567-3.335,1.857-6.615,3.859-9.853 c1.999-3.236,5.236-5.47,9.706-6.708c4.476-1.24,10.424-1.858,17.85-1.858h40.539V0h-64.809c-37.5,0-64.433,8.897-80.803,26.691 c-16.368,17.798-24.551,44.014-24.551,78.658v48.82h-48.542v81.086h48.539v235.256h97.362V235.256h64.805l8.566-81.086H271.521z"/> </g> </svg> </span></a> </div> </div> </div> </div> </div> <!-- End of card --> </div> <div class="blog-card-wrapper full"> <!-- Since we have groups of 3 on the page we create a few generic cards to match groups of 3 (as needed). Otherwise the last line is taken up completely by a stretched out card or by 2 stretched out cards. For the time being these extra cards are hidden. --> <!-- If we need to add a card on the last line --> <!-- If we need to add a second card on the last line --> </div> </div> </div> </div> <div id="next-page" class="scroll"> <div class="full row lt-grey-bg center"> <a id="next" href=" /talks/?page=2" class="hollow-button-blue"> View more talks <span class="fa"><?xml version="1.0" encoding="utf-8"?> <svg width="20" height="20" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><title>Plus</title><path d="M1344 960v-128q0-26-19-45t-45-19h-256v-256q0-26-19-45t-45-19h-128q-26 0-45 19t-19 45v256h-256q-26 0-45 19t-19 45v128q0 26 19 45t45 19h256v256q0 26 19 45t45 19h128q26 0 45-19t19-45v-256h256q26 0 45-19t19-45zm320-64q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/></svg></span> </a> </div> </div> </section> <section> <!-- BOOKS PREVIEW CARDS --> <div id="books-section" class="full blue-bg cushion-big-space our-books"> <div class="wrapper"> <h2 class="section-title center white"> <div>Books</div> </h2> <div class="three-quarters"> <div class="white"> <div>Our team鈥檚 published books give you a detailed look into building thoughtful web applications with high code quality.</div> </div> </div> <div class="blog-card-wrapper full underline-link"> <div class="card-horizontal"> <div class="third"> <a href="http://shop.oreilly.com/product/0636920032502.do" target="_blank"> <img src="https://storage.caktusgroup.com/media/resources/books/lightweightdjangocover.gif" alt=""> </a> </div> <div class="two-thirds card-info-book"> <a href="http://shop.oreilly.com/product/0636920032502.do" class="title" target="_blank">Lightweight Django </a> <p> <!-- Caktus authors' names are green; otherwise black --> <span class="author-non-caktus"> Julia Elman</span> & <!-- Caktus authors' names are green; otherwise black --> <span class="author-non-caktus"> Mark Lavin</span> </p> <p class="synopsis"> <div>A guide for intermediate Django users to hone their skills.</div> </p> <a href="http://shop.oreilly.com/product/0636920032502.do" class="purchase-from" target="_blank"> Purchase from O&#39;Reilly Media </a> </div> </div> <div class="card-horizontal"> <div class="third"> <a href="http://shop.oreilly.com/product/9781847197566.do" target="_blank"> <img src="https://storage.caktusgroup.com/media/resources/books/karen-book_1.jpg" alt=""> </a> </div> <div class="two-thirds card-info-book"> <a href="http://shop.oreilly.com/product/9781847197566.do" class="title" target="_blank">Django 1.1 Testing and Debugging </a> <p> <!-- Caktus authors' names are green; otherwise black --> <span class="author"><a href="/about/karen-tracey/"> Karen Tracey</a></span> </p> <p class="synopsis"> <div>A Django classic text on debugging that still holds true today.</div> </p> <a href="http://shop.oreilly.com/product/9781847197566.do" class="purchase-from" target="_blank"> Purchase from Packt Publishing </a> </div> </div> </div> </div> </div> </section> <!-- END OF THE ROAD --> </main><!-- /end mainContent --> </div><!-- /end wrap --> <footer id="footer" class="full footer"> <div class="wrapper"> <div class="half"> <div class="half"> <div><h3>Contact us</h3></div> <p> <a href="mailto:solutions@caktusgroup.com" target="_blank">solutions@caktusgroup.com</a> </p> <p> T 919-951-0052 <br> F 919-928-5516 </p> <p> 108 Morris St, Suite 2<br> Durham, NC 27701<br> </p> </div> <div class="half site-map"> <div><h3>Quick links</h3></div> <ul> <li><a href="/services/">Services</a></li> <li><a href="/casestudies/">Our work</a></li> <li><a href="/about/">About us</a></li> <li><a href="/blog/">Blog</a></li> <li><a href="/careers/">Careers</a></li> <li><a href="/events/">Events</a></li> <li><a href="/talks/">Talks</a></li> <li><a href="/ebooks/">Ebooks</a></li> <li><a href="/press/">Press</a></li> <li><a href="/contact/">Contact</a></li> </ul> </div> </div><!--End first half--> <div class="half"> <div class="half newsletter-sign-up"> <div><h3>Newsletter</h3></div> <form action="/subscribe/" method="post" class="newsletter-form form-inline" novalidate> <input type="hidden" name="csrfmiddlewaretoken" value="25LDRWSw3nS4BQe2quHJ18GoYenU9jvc6BpWFKM6IY61crJlCUTtJVir9Vg4CTGw"> <div style="display: none;"> <label> Leave this blank to prove your humanity: <input type="text" name="body" value="" /> </label> </div> <ul class="errors list-unstyled"></ul> <label class="sr-only" for="id_email"> Email address </label> <div class="sign-up-container"> <span class="icon"> <button type="submit" aria-label="Submit"> <span class="fa grey"><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 511.626 511.627" style="enable-background:new 0 0 511.626 511.627;" xml:space="preserve"> <title>Envelope</title> <g> <path d="M498.208,68.235c-8.945-8.947-19.701-13.418-32.261-13.418H45.682c-12.562,0-23.318,4.471-32.264,13.418 C4.471,77.18,0,87.935,0,100.499v310.633c0,12.566,4.471,23.312,13.418,32.257c8.945,8.953,19.701,13.422,32.264,13.422h420.266 c12.56,0,23.315-4.469,32.261-13.422c8.949-8.945,13.418-19.697,13.418-32.257V100.499 C511.626,87.935,507.158,77.18,498.208,68.235z M475.078,411.125c0,2.475-0.903,4.616-2.714,6.424 c-1.81,1.81-3.949,2.706-6.42,2.706H45.679c-2.474,0-4.616-0.896-6.423-2.706c-1.809-1.808-2.712-3.949-2.712-6.424V191.858 c6.09,6.852,12.657,13.134,19.7,18.843c51.012,39.209,91.553,71.374,121.627,96.5c9.707,8.186,17.607,14.561,23.697,19.13 c6.09,4.571,14.322,9.185,24.694,13.846c10.373,4.668,20.129,6.991,29.265,6.991h0.287h0.284c9.134,0,18.894-2.323,29.263-6.991 c10.376-4.661,18.613-9.274,24.701-13.846c6.089-4.569,13.99-10.944,23.698-19.13c30.074-25.126,70.61-57.291,121.624-96.5 c7.043-5.708,13.613-11.991,19.694-18.843V411.125L475.078,411.125z M475.078,107.92v3.14c0,11.229-4.421,23.745-13.271,37.543 c-8.851,13.798-18.419,24.792-28.691,32.974c-36.74,28.936-74.897,59.101-114.495,90.506c-1.14,0.951-4.474,3.757-9.996,8.418 c-5.514,4.668-9.894,8.241-13.131,10.712c-3.241,2.478-7.471,5.475-12.703,8.993c-5.236,3.518-10.041,6.14-14.418,7.851 c-4.377,1.707-8.47,2.562-12.275,2.562h-0.284h-0.287c-3.806,0-7.895-0.855-12.275-2.562c-4.377-1.711-9.185-4.333-14.417-7.851 c-5.231-3.519-9.467-6.516-12.703-8.993c-3.234-2.471-7.614-6.044-13.132-10.712c-5.52-4.661-8.854-7.467-9.995-8.418 c-39.589-31.406-77.75-61.57-114.487-90.506c-27.981-22.076-41.969-49.106-41.969-81.083c0-2.472,0.903-4.615,2.712-6.421 c1.809-1.809,3.949-2.714,6.423-2.714h420.266c1.52,0.855,2.854,1.093,3.997,0.715c1.143-0.385,1.998,0.331,2.566,2.138 c0.571,1.809,1.095,2.664,1.57,2.57c0.477-0.096,0.764,1.093,0.859,3.571c0.089,2.473,0.137,3.718,0.137,3.718V107.92 L475.078,107.92z"/> </g> </svg> </span> </button> </span> <input type="email" value="" name="email" style="border: none" id="id_email" class="form-control" placeholder="youremail@email.com" required /> <input type="hidden" name="page_name" id="id_page_name"> </div> </form> <div class="newsletter-info"> <div>Get tips, see case studies, and stay up to date on Caktus news. <br><a href="https://learn.caktusgroup.com/newsletter" style="font-weight: bold;">Learn more.</a></div> </div> <p> <a href="https://www.iubenda.com/privacy-policy/91739120">Privacy Policy</a> </p> <p> <a href="https://www.iubenda.com/privacy-policy/91739120/cookie-policy">Cookie Policy</a> </p> </div> <div class="half social-media"> <div id="socialicons" class="socialicons"> <div><h3>Follow us</h3></div> <ul> <li> <a href="https://twitter.com/caktusgroup" target="_blank"> <span class="fa grey"><svg version="1.1" id="svg_twitter" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 449.956 449.956" style="enable-background:new 0 0 449.956 449.956;" xml:space="preserve"> <title>Twitter</title> <g> <path d="M449.956,85.657c-17.702,7.614-35.408,12.369-53.102,14.279c19.985-11.991,33.503-28.931,40.546-50.819 c-18.281,10.847-37.787,18.268-58.532,22.267c-18.274-19.414-40.73-29.125-67.383-29.125c-25.502,0-47.246,8.992-65.24,26.98 c-17.984,17.987-26.977,39.731-26.977,65.235c0,6.851,0.76,13.896,2.284,21.128c-37.688-1.903-73.042-11.372-106.068-28.407 C82.46,110.158,54.433,87.46,31.403,59.101c-8.375,14.272-12.564,29.787-12.564,46.536c0,15.798,3.711,30.456,11.138,43.97 c7.422,13.512,17.417,24.455,29.98,32.831c-14.849-0.572-28.743-4.475-41.684-11.708v1.142c0,22.271,6.995,41.824,20.983,58.674 c13.99,16.848,31.645,27.453,52.961,31.833c-7.995,2.091-16.086,3.138-24.269,3.138c-5.33,0-11.136-0.475-17.416-1.42 c5.9,18.459,16.75,33.633,32.546,45.535c15.799,11.896,33.691,18.028,53.677,18.418c-33.498,26.262-71.66,39.393-114.486,39.393 c-8.186,0-15.607-0.373-22.27-1.139c42.827,27.596,90.03,41.394,141.612,41.394c32.738,0,63.478-5.181,92.21-15.557 c28.746-10.369,53.297-24.267,73.665-41.686c20.362-17.415,37.925-37.448,52.674-60.097c14.75-22.651,25.738-46.298,32.977-70.946 c7.23-24.653,10.848-49.344,10.848-74.092c0-5.33-0.096-9.325-0.287-11.991C421.785,120.202,437.202,104.306,449.956,85.657z"/> </g> </svg> </span> </a> </li> <li> <a href="https://github.com/caktus" target="_blank"> <span class="fa grey"><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.549 438.549" style="enable-background:new 0 0 438.549 438.549;" xml:space="preserve"> <title>Github</title> <g> <path d="M409.132,114.573c-19.608-33.596-46.205-60.194-79.798-79.8C295.736,15.166,259.057,5.365,219.271,5.365 c-39.781,0-76.472,9.804-110.063,29.408c-33.596,19.605-60.192,46.204-79.8,79.8C9.803,148.168,0,184.854,0,224.63 c0,47.78,13.94,90.745,41.827,128.906c27.884,38.164,63.906,64.572,108.063,79.227c5.14,0.954,8.945,0.283,11.419-1.996 c2.475-2.282,3.711-5.14,3.711-8.562c0-0.571-0.049-5.708-0.144-15.417c-0.098-9.709-0.144-18.179-0.144-25.406l-6.567,1.136 c-4.187,0.767-9.469,1.092-15.846,1c-6.374-0.089-12.991-0.757-19.842-1.999c-6.854-1.231-13.229-4.086-19.13-8.559 c-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559 c-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-0.951-2.568-2.098-3.711-3.429c-1.142-1.331-1.997-2.663-2.568-3.997 c-0.572-1.335-0.098-2.43,1.427-3.289c1.525-0.859,4.281-1.276,8.28-1.276l5.708,0.853c3.807,0.763,8.516,3.042,14.133,6.851 c5.614,3.806,10.229,8.754,13.846,14.842c4.38,7.806,9.657,13.754,15.846,17.847c6.184,4.093,12.419,6.136,18.699,6.136 c6.28,0,11.704-0.476,16.274-1.423c4.565-0.952,8.848-2.383,12.847-4.285c1.713-12.758,6.377-22.559,13.988-29.41 c-10.848-1.14-20.601-2.857-29.264-5.14c-8.658-2.286-17.605-5.996-26.835-11.14c-9.235-5.137-16.896-11.516-22.985-19.126 c-6.09-7.614-11.088-17.61-14.987-29.979c-3.901-12.374-5.852-26.648-5.852-42.826c0-23.035,7.52-42.637,22.557-58.817 c-7.044-17.318-6.379-36.732,1.997-58.24c5.52-1.715,13.706-0.428,24.554,3.853c10.85,4.283,18.794,7.952,23.84,10.994 c5.046,3.041,9.089,5.618,12.135,7.708c17.705-4.947,35.976-7.421,54.818-7.421s37.117,2.474,54.823,7.421l10.849-6.849 c7.419-4.57,16.18-8.758,26.262-12.565c10.088-3.805,17.802-4.853,23.134-3.138c8.562,21.509,9.325,40.922,2.279,58.24 c15.036,16.18,22.559,35.787,22.559,58.817c0,16.178-1.958,30.497-5.853,42.966c-3.9,12.471-8.941,22.457-15.125,29.979 c-6.191,7.521-13.901,13.85-23.131,18.986c-9.232,5.14-18.182,8.85-26.84,11.136c-8.662,2.286-18.415,4.004-29.263,5.146 c9.894,8.562,14.842,22.077,14.842,40.539v60.237c0,3.422,1.19,6.279,3.572,8.562c2.379,2.279,6.136,2.95,11.276,1.995 c44.163-14.653,80.185-41.062,108.068-79.226c27.88-38.161,41.825-81.126,41.825-128.906 C438.536,184.851,428.728,148.168,409.132,114.573z"/> </g> </svg> </span> </a> </li> <li> <a href="https://www.facebook.com/CaktusGroup" target="_blank"> <span class="fa grey"><svg version="1.1" id="svg_facebook" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 470.513 470.513" style="enable-background:new 0 0 470.513 470.513;" xml:space="preserve"> <title>Facebook</title> <g> <path d="M271.521,154.17v-40.541c0-6.086,0.28-10.8,0.849-14.13c0.567-3.335,1.857-6.615,3.859-9.853 c1.999-3.236,5.236-5.47,9.706-6.708c4.476-1.24,10.424-1.858,17.85-1.858h40.539V0h-64.809c-37.5,0-64.433,8.897-80.803,26.691 c-16.368,17.798-24.551,44.014-24.551,78.658v48.82h-48.542v81.086h48.539v235.256h97.362V235.256h64.805l8.566-81.086H271.521z"/> </g> </svg> </span> </a> </li> <li> <a href="https://www.linkedin.com/company/caktus-consulting-group-llc" target="_blank"> <span class="fa grey"><svg version="1.1" id="svg_linkedin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="0 0 438.536 438.535" style="enable-background:new 0 0 438.536 438.535;" xml:space="preserve"> <title>LinkedIn</title> <g> <g> <rect x="5.424" y="145.895" width="94.216" height="282.932"/> <path d="M408.842,171.739c-19.791-21.604-45.967-32.408-78.512-32.408c-11.991,0-22.891,1.475-32.695,4.427 c-9.801,2.95-18.079,7.089-24.838,12.419c-6.755,5.33-12.135,10.278-16.129,14.844c-3.798,4.337-7.512,9.389-11.136,15.104 v-40.232h-93.935l0.288,13.706c0.193,9.139,0.288,37.307,0.288,84.508c0,47.205-0.19,108.777-0.572,184.722h93.931V270.942 c0-9.705,1.041-17.412,3.139-23.127c4-9.712,10.037-17.843,18.131-24.407c8.093-6.572,18.13-9.855,30.125-9.855 c16.364,0,28.407,5.662,36.117,16.987c7.707,11.324,11.561,26.98,11.561,46.966V428.82h93.931V266.664 C438.529,224.976,428.639,193.336,408.842,171.739z"/> <path d="M53.103,9.708c-15.796,0-28.595,4.619-38.4,13.848C4.899,32.787,0,44.441,0,58.529c0,13.891,4.758,25.505,14.275,34.829 c9.514,9.325,22.078,13.99,37.685,13.99h0.571c15.99,0,28.887-4.661,38.688-13.99c9.801-9.324,14.606-20.934,14.417-34.829 c-0.19-14.087-5.047-25.742-14.561-34.973C81.562,14.323,68.9,9.708,53.103,9.708z"/> </g> </g> </svg> </span> </a> </li> <li> <a href="https://www.youtube.com/channel/UCfA4g648eBpPyhNy-eHP0-A" target="_blank"> <span class="fa grey"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 176 124" width="20px" height="20px" > <g id="Layer_2" data-name="Layer 2"> <g id="Layer_1-2" data-name="Layer 1"> <path class="cls-1" d="M172.32,19.36A22.12,22.12,0,0,0,156.76,3.7C143,0,88,0,88,0S33,0,19.24,3.7A22.12,22.12,0,0,0,3.68,19.36C0,33.18,0,62,0,62s0,28.82,3.68,42.64A22.12,22.12,0,0,0,19.24,120.3C33,124,88,124,88,124s55,0,68.76-3.7a22.12,22.12,0,0,0,15.56-15.66C176,90.82,176,62,176,62S176,33.18,172.32,19.36Z"/> <polygon class="cls-2" points="70 88.17 116 62 70 35.83 70 88.17"/> </g> </g> </svg></span> </a> </li> </ul> </div> <div class="twitter-feed"> <a class="twitter-timeline" href="https://twitter.com/caktusgroup" data-widget-id=616657501325541376 data-tweet-limit="1" data-chrome="noheader noborders transparent nofooter"></a> <script>!function(d,s,id) {var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https'; if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js"; fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs"); </script> </div> </div> </div><!--End second half--> </div><!--End wrapper--> </footer> <div class="modal fade" id="newsletter-modal" role="dialog" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"> <span aria-hidden="true">&times;</span> <span class="sr-only">Close</span> </button> <h4>Success!</h4> </div> <div class="modal-body"></div> <div class="modal-footer"> <button type="button" class="btn btn-primary" data-dismiss="modal"> Close </button> </div> </div> </div> </div> <script src="https://storage.caktusgroup.com/static/js/bundle.80f81ff0dc33.js"></script> <script type="text/javascript"> var _iub = _iub || []; _iub.csConfiguration = { cookiePolicyId: 91739120, siteId: 1020454, lang: "en" } ; </script> <script type="text/javascript" src="//cdn.iubenda.com/cookie_solution/safemode/iubenda_cs.js" charset="UTF-8" async></script> <!-- Start of Async HubSpot Analytics Code --> <script type="text/javascript"> (function(d,s,i,r) { if (d.getElementById(i)){return;} var n=d.createElement(s),e=d.getElementsByTagName(s)[0]; n.id=i;n.src='//js.hs-analytics.net/analytics/'+(Math.ceil(new Date()/r)*r)+'/1883108.js'; e.parentNode.insertBefore(n, e); })(document,"script","hs-analytics",300000); </script> <!-- End of Async HubSpot Analytics Code --> <!-- Start of Adroll Code --> <script type="text/javascript"> adroll_adv_id = "4SXKCPWKKVFL7CGO4ABFGD"; adroll_pix_id = "S3NXO4MKCNCNTJCTD7FQ3F"; (function () { var _onload = function(){ if (document.readyState && !/loaded|complete/.test(document.readyState)){setTimeout(_onload, 10);return} if (!window.__adroll_loaded){__adroll_loaded=true;setTimeout(_onload, 50);return} var scr = document.createElement("script"); var host = (("https:" == document.location.protocol) ? "https://s.adroll.com" : "http://a.adroll.com"); scr.setAttribute('async', 'true'); scr.type = "text/javascript"; scr.src = host + "/j/roundtrip.js"; ((document.getElementsByTagName('head') || [null])[0] || document.getElementsByTagName('script')[0].parentNode).appendChild(scr); }; if (window.addEventListener) {window.addEventListener('load', _onload, false);} else {window.attachEvent('onload', _onload)} }()); </script> <!-- End of Adroll Code --> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10