
Elm Radio
96 episodes — Page 2 of 2
Ep 46046: 2021 Holiday Special!
Our special guestsRyan Haskell-Glatz (twitter) (github)Brian Hicks (twitter) (github)Robin Heggelund Hansen (twitter) (github)
Ep 45045: How We Learn
Make impossible states impossibleTeaching elm episodeDillon's first Elm project, Mobster pair/mob programming timerIdeas for Effective LearningHave a playground to try out ideasTry a new tool or technique with a familiar problem or exerciseSmall scale exercises and real world projectsSmall scale exercises are helpful for quickly developing a skillFeedback loopsTiny steps shorten the feedback loopUse code katas like bowling, tennis, roman numeral katasAnalogous to empirical scientific method (hypothesis, test, analyze)Call your shotDon't forget to analyze test results afterListen to smart people, but come to your own conclusionsTry two alternate ways of doing something out for yourselfFailure is part of learningFollow your curiosityLook at the source for projects you depend on or come acrossGrowth Mindset vs. Fixed MindsetYou have to make knowledge your own (synthesis) - connect it to what you knowJust in time vs. just in case learning - focus on what you need or seems important nowFlexbox Froggy gameDemystify things (for example custom type constructors vs type alias constructors)Mind mappingElm Radio Opaque Types episodeZettlekasten second brainHow to Take Smart Notes bookMake declarative statements in second brain systemDillon's use the platform note from his digital gardenDigital gardeningLearn in public movementRichard Feldman's talk Scaling Elm AppsRichard experimenting with dream writer in a component architectMake It Stick book (and some notes summarizing key ideas)Elm Radio API Design Lessons episodeLet your background processing do some work for youDan Pink's book WhenEarly bird vs night owl thinkingJeroen's blog
Ep 44044: elm-webgl
Guest: Andrey Kuzmin (github) (twitter)elm-explorations/webglGLSL syntaxTwo shaders: vertex shader and fragment shaderUniforms are declarative bindings to Elm values. Type safe mappingSimple cube exampleelm-explorations/linear-algebra/latestProjection matriceselm-webgl-lessonsianmackenzie/elm-3d-scene/latest/Luca's listing of 3d Elm examples and resourceselm-3d-scene exampleselm-csg (Constructive solid geometry)Elm Japan 3d SVG art#gamedev and #webgl channels in Elm SlackJames Carlson's talk about communicating with the GPU from Elm using Futhark: Making Elm Talk to Your Personal SupercomputerAndrey's elm-webgl-playground examples
Ep 43043: Teaching Elm with Richard Feldman
Richard Feldman (Twitter) (GitHub)Richard's Elm book Elm in ActionRichard's Frontend Masters coursesRichard's talk Teaching Elm to BeginnersFind motivationMloc.js conference (by Prezi)Pairing as a way to teach ElmIntro to Elm Frontend Masters workshop exercises are open sourceSouth Park therefore/but storytelling technique"I like teaching things the wrong way and then showing what's wrong with it."The importance of finding good examplesTraining From the Back of the RoomDillon's Elm JSON Decoder koans repoGradual release of responsibility techniqueBrian's JSON Survival Kit bookNoRedInk jobs (looking for Elm and Haskell engineers)Richard's Frontend Masters advanced Elm course and Elm intro course
Ep 42042: Comparing TypeScript and Elm's Type Systems
TypeScript and Elm have different goalsSoundness is not a goal of the TypeScript type systemTypeScript Design Goals (and non-goals)TypeScript's any typeNominal vs structural typingTypeScript's any vs. Elm's Debug.todoTypeScript's any essentially "turns off" type checking in areas that any passes through.In Elm:You can get a type that could be anything with Debug.todo, but you can't build your app with --optimize if it has Debug.todo's in itYou will still get contradictions between inconsistent uses of a type that could be anything (see this Ellie example)This Ellie example (with compiler error as expected) and this TypeScript playground example (with no error) show the difference.any can not be used in places that take neverany vs unknownJSON.parse returns any, as do many core and published typingsio-ts lets you validate JSON similar to JSON decoders in ElmDefinitely Typed (published type definitions for NPM packages)Definitely Typed searchnoImplicitAnyTypeScript `strict mode in tsconfigDillon's post TypeScript's Blind SpotsJS semantics allow types that may not be intended (like adding a string + object, '' + {} === '[object Object]')Function parameters are inferred to be any regardless of implementation if they aren't given an explicit typeType narrowingTypeScript has untagged unions (just called Unions) - in Elm, there are only tagged unions (called Custom Types)Undefined vs nullTypeScript's Void typeTypeScript doesn't have checked exceptions like Java (there is a discussion about this on GitHub) - Elm only has explicit errors as data that must be handled exhaustively like other data typesDiscriminated unions vs Elm custom typesLiteral typesTypeScript allows number literal values, but arithemtic expressions return generic number values instead of literal typesEnumsBranded types in TypeScript vs opaque typesElm Radio Opaque Types episodeSwitch statements are not exhaustive - you can add an eslint rule to check that (or the never trick, assert unreachable)Key of operator in TypeScriptTypeScript's type system can do some cool things that Elm can't (for better and for worse)PrismaPrisma advanced TS meetup talksTuples in TypeScript are just arrays and use narrowing - Tuple in Elm is a specific typeelm-ts-interopTypeScript handbook on official site
Ep 41041: elm-markdown
dillonkearns/elm-markdownMarkdown was built to be friendly to humans more than parsers. Example of a markdown quirk for human-friendliness: numbered lists starting with 1 interrupt paragrpahs, starting with other numbers don'tBabelmark helps compare output of different markdown implementationsSome parts of the markdown spec are ambiguousJohn Gruber created markdown (Daring Fireball)Jeff Atwood pushed for CommonMark specCommonMarkGitHub-Flavored Markdown (gfm) is a superset of CommonMark (Auto-links, Todo syntax, tables, etc.)Bear notes app (Mac only)dillonkearns/elm-markdown's Core Tools for ExtensibilityCustom RenderersHtml handlers (example)Transforming parsed Markdown Blocks (AST)incrementalelm.com code for getting back references from parsed markdownJeroen's Hierarchy of Constraints noteHelpers for folding over Blocks and InlinesExtracting table of contents exampleDiscussion to formalize HTML parsing and error handling spec in dillonkearns/elm-markdownExample of unintuitive raw HTML tag handling in markdown: <span> closed by whitespace (ignores closing tag)ZettlekastenWikilinksFoam ResearchGFM Autolinks extensionelm-explorations/markdownMatthew Griffith's elm-markup packageMatt's Oslo talk on fault tolerant parsing A Markup for the Statically Typedelm-optimize-level-2ShikiDecksetUnifiedJS markdown transformation ecosystemelm-markdown-transformsRender to a function (example)Scheme evaluator example (demo) (code)elm-pages 2.0 episodeMarkdown announcement blog post Extensible Markdown Parsing in Pure Elm#markdown channel in The Elm SlackExample of extracting title and description from parsed markdownElm Online MeetdownSubmit a talk proposal to the Elm Online Call for Speakers form
Ep 40040: Phantom Builder Pattern
Phantom types (happens at compile time, not runtime)Helps avoid things like adding centimeters and inchesianmackenzie/elm-unitsJoël Quenneville's phantom types talk from Elm in the Spring A Number by Any Other NameExtensible recordsBuilder patternJeroen's Hierarchy of Constraintselm-graphql SelectionSet scope type variableBuilder Pattern episodeBrian Hicks' builder pattern talk Robot Buttons from Marswith functionsPhantom builder is a state machine for your typeselm-review Rule API uses phantom builderPhantom types discourse post on time package Simon HertebySnapshot test in Elm review for expected error messagesPhantom Builder live stream episodePossible operations with phantom extensible buildersAdd a new fieldRemove a fieldChange the type of a fieldRemove the previously existing phantom type and change it to an empty record (not extensible, just a hardcoded return type) i.e. ReplaceWhat you can do with phantom builderRequire something to be always calledForbid something being called more than onceCause other constraints dynamically after calling somethingMake function calls mutually exclusiveEnable a function only if another one has been called
Ep 39039: elm-charts
Tereza Sokol (GitHub) (Twitter)terezka/elm-chartselm-charts.orgOriginal APIs: line-charts and elm-plotTereza's Elm Europe talk elm-plot: the big pictureTereza's talk If Coco Chanel Reviewed ElmEdward TufteNew version tries to be less prescriptiveExtensible Web Manifestogampleman/elm-visualizationelm-vegaGHCJS (mentioned in Elm Town episode 6)
Ep 38038: Lamdera
Mario Rogic (GitHub) (Twitter)LamderaLamdera 1.0 releaseElm Europe conference talk introducing LamderaElm Europe conference talk about Lamdera's EvergreenLamdera is about removing non-essential complexity - 6 conceptsStuff that happens for the client (in the browser)Stuff that happens in the server (like scheduled job)Data from client to backendData from backend to clientFrontend knows what it knowsBackend knows what it knowsLamdera docsSemantic boundaries (remove glue code)Real-time chat example app and other Lamdera example appsLamdera "Anti-Marketing" pageLamdera Discordelm-pkg-js specElm Online meetdown groupCalls email sending service through HTTPMartin Fowler's "Memory Image" ideaEvent SourcingMartin Stewart talk introducing a Lamdera end-to-end testing toolWire size improvement in Lamdera alpha12 release noteselm-webappLamdera real world repo (PR 1) (PR 2)
Ep 37037: Performance in Elm
elm-review-performanceTail call optimizationsJeroen's blog post on Tail-call optimization in ElmEvan Czaplicki's chapter on Tail-Call Optimization and how to write optimized codeLighthouse Elm Radio episodeJu Liu's Performant Elm blog post seriesAvoid memoized state when possible to avoid stale dataHtml.LazyElm's html lazy only works when the function and args have the same reference as before. List.map will return a list with a new reference, for example.Elm has function-level dead code eliminationReferencing a record pulls the whole record in no matter how many fields are used directlybcp-47-language-tag packageElm list extra gets split by function, unlike lodash which needs to be splitElm Core Dict package has O(logn) complexity for operations like insertJavaScript Objects aren't optimized for removing/adding properties"What's Up With Monomorphism"elm-optimize-level-2elm-explorations/benchmarkJeroen's list-extra PRs (with reference to the benchmark for it) for functions gatherWith isInfixOfwebpagetest.org (or web.dev performance testing)Netlify Lighthouse pluginRSLint - fast version of ESLint, but doesn't have custom rulesInstructions to minify Elm codeJake and Surma talk about optimizing sites - Setting up a static render in 30 minutesJake Archibald's talk explaining JavaScript's event loop and requestAnimationFrame - In The Loop
Ep 36036: elm-pages 2.0
Introducing elm-pages v2!Pre-rendered pageselm-pages has a build stepParse, Don't validateFrontmatterDataSource.FileDataSource.failDataSource.GlobDistill API DataSource.distillCodecelm-graphql DataSource example from incrementalelm.comThe 2.0 docs are at elm-pages.com#elm-pages channel on the Elm SlackIncremental Elm source codeElm Radio site source code
Ep 35035: elm-spa v6
Ryan Haskell-Glatz (Twitter) (GitHub)elm-spa V5 Docselm-spa v5 episodeKey new features in v6Protected pagesProvide/redirect protected custom typeEject workflowVuepresselm-program-test docs siteCan Eject not found pageEject workflow stops generating files when they're ejectedFile-based routing in elm-spaInspired by NuxtPage builder API (like browser sandbox)No more int or string in urlelm-pages 2.0 routing and splat routeselm-spa add commandelm-liveViteelm-spa View moduleUI namespace in elm-spa docs repo has a shared page helper function for building the shared header/footerShared moduleelm-spa 6 has fewer ignored arguments compared to v5 - now wired through in page top level function and you can wire to update, init, etc.Effect pattern - elm-spa v6 has an ejectable Effect moduleelm-real-world SPA example (elm-spa-example using elm-spa framework)elm-spa.develm-program-test example folderBlissfully jobs#elm-spa-users channel on the Elm Slack
Ep 34034: API Design Lessons
Idiomatic Elm package guidedillonkearns/elm-package-starterLessonsAvoid unexpected or silent behaviorGive context/feedback when things go wrong so the user knows their change was registered, to enhance trustGood errors aren't just for beginners - Curb Cut EffectSandi metz - code has a tendency to be duplicated - be a good role model - we're influenced by precedenceMatt Griffith - API design is holistic. It's a problem domain. Rethink from the ground up.Learn from the domain and terms, but don't limit yourself to it when you can create better abstractions.Linus Torvalds' definition of elegance/good taste - recognize two code paths as one. Reduce the number of concepts in your API when you can treat two things as one, then things compose more easily. How Elm Code Tends Towards Simplicity.You don't need a direct mapping of your domain, but start with the spec and terms. Leverage existing concepts, and have an economy of concepts. Tereza's talk: elm-plot The Big PictureAPI design is a tool to help you solve problems.There's a qualitative difference when you wire up feedback before you up front.Avoid toy examples, use meaningful use cases to direct your design.Design for concrete use cases, and drive changes through feedback from concrete use cases. Legal standing. Better to do it right than to do it right now Evan's concept from the Elm philosophy. If you don't have a motivating use case, then wait. Extract APIs from real world code. It's okay for there to be duplication. Premature abstraction is the root of all evil. sSmplicity is the best thing you can do to anticipate future API design needs.Come up with an API with the most benefits and the least pain points.If there's something that you want to make really good, invest in giving it a good feedback mechanism.Rich Hickey's talk Hammock Driven Development. We don't design APIs, our extremely creative subconscious designs APIs - let your conscious brain do the hard work to put all the information in front of your subconscious so it can do what it does best. elm-pages 2.0 screencast with Jeroen and Dillon.Pay no attention to the man behind the curtain. Parse, Don't validate at the high level, but under the hood you may need a low level implementation.Have a clear message/purpose - whether it's an API, or an internal module.Take responsibility for user experiences.
Ep 33033: Accessibility in Elm
Tessa Kelly (GitHub) (Twitter)The 4 Principles of Accessibilityprefers-reduced-motion media queryGuide to using Mac's built-in VoiceOver screenreaderAce Accessibility toolsSkip LinksNavigating headings with a screenreader (see keyboard shortcuts for the VoiceOver rotor)WCAG checklistsVPAT documentsARIA attributesThe Accessibility TreeGoogle's explanation of The Accessibility TreeAn API for the Accessibility Object Model is in draft formAvoid modals, instead try a different uxAccessible radio buttonsTessa's Accessible HTML package tesk9/accessible-htmllist-style-image in CSSProgressive enhancementRemix's approach to progressively enhancing formsPackage for using Accessibile HTML with elm-css - tesk9/accessible-html-with-cssJeroen's hierarchy of static checksChorded keyboardEmily Shea's talk Voice Driven Development: Who needs a keyboard anyway?WCAG accessibility guidelineswebaim.orgAngela Hooker's Juneteenth Conf talk Empowerment to the People! What You Need to Know about Black People, Disability, and AccessibilityAxeCon talksDeque's education resources site - Deque UniversityAxe Dev tools Chrome extensionTessa Kelly (GitHub) (Twitter)NoRedInk jobs
Ep 32032: Elm's Universal Pattern
Joël Quenneville (Twitter)Joël's blog post Elm's Universal Patternmap2Maybe.map2MetaphorsSome common metaphors for Elm's Universal Pattern (Applicative Pattern).MappingCombiningLiftingWrapping and unwrapping boxesBlog post on Two ways of looking at map functionsExamplesRandom generatorsApply mapping functions to vanilla value functions to keep things cleanTipsSeparate branching code from doing code (discussed in-depth in Joël's blog post Problem Solving with Maybe)Stay at one level of abstractionJson decoders as combining functionsScott Wlaschin Railway Oriented ProgrammingDillon's blog post Combinators - Inverting Top-Down TransformsThe JSON structure and Elm type don't have to mirror each other - start with your ideal type and work backwardsApplicative patternApplicative needs 1) way to construct, 2) map2 or andMapJson.Decode.Pipeline.required functionRecord constructorsPractice writing it with an anonymous function to convince yourself it's equivalentRecord constructors are just a plain old elm functionmap2 doesn't take a type, it takes a function -NoRedInk/elm-json-decode-pipeline is a useful reference for implementing this kind of api on your ownApplicative Laws in HaskellMonomorphic vs polymorphicParser Combinatorselm/parser episodeJoël's blog posts on the ThoughtBot blogJoël's Random generators talkJoël's Maybe talkSome more blog posts by Joël that related to Elm's Universal Pattern:Running out of mapsPipeline Decoders in ElmJoël's journey to building a parser combinator:Nested cases - https://ellie-app.com/b9nGmZVp9Vca1Extracted Result functions - https://ellie-app.com/b9qtqTf8zYda1Introducing a Parser alias and map2 - https://ellie-app.com/b9MwZ3y4t8ra1Re-implementing with elm/parser - https://ellie-app.com/b9NZhkTGdfya1Getting Unstuck with Elm JSON Decoders - because mapping is universal, you can solve equivalent problems with the same pattern (described in this post)
Ep 31031: Elm Code Generation
What's the source of truth?Teach the Elm compiler about external things like schemaselm-graphqldillonkearns/elm-graphqlTypes Without BordersMacros in other languagesC macros compared to Lisp macrosReScript ppx macrosVanilla code generation can be inspected and debugged like plain handwritten codeGitignore gen code so you know you didn't forget to generate it on the build serverWatchers for rerunning codegenRerun code gen when the source of truth changes ideallyChokidar CLIThe Design of Everyday Things by Donald NormanAffordancesMappingselm-tailwind-modulesChadtech/elm-vectorthe-sett/salixelm-ts-interopScaffoldingelm-review init, new-rule, and new-packageelm-spa newhtml-to-elm.comEnd to end testing your generated codeSnapshot testingelm-graphql's snapshot testing scripthtml-to-elm.com generated test suiteelm-verify-examples
Ep 30030: Debugging in Elm
Rubber duckingLay out your assumptions explicitlyVeritasium video The Most Common Cognitive BiasElm Debugging techniquesDebug.todoFrame then fill inAnnotation let bindingsUsing nonsense names as a stepElm review rule to check for nonsense nameHardcoded values vs debug.todoTodos don't allow you to get feedback by running your codeTDDFake it till you make itSimplest thing that could possibly workJoël Quenneville's article Classical Reasoning and DebuggingDebugging is like pruning a treeBreaksTake a walk. Step away from the keyboard when you're grinding on a problemsscce.org (Short, Self Contained, Correct (Compilable), Example)Create a smaller reproduction of the problemReduce the variables, you reduce the noise and get more useful feedbackReasoning by analogy from Joël's postElm debug log browser extensionnode --inspectelm-test-rsDebug.log in unit testsTest.only for running just one test or describePut Debug.logs in each path of an if or case expressionUse the browser elm debugger to inspect the modelScaling Elm Application episodeNarrow down your search space with Elm typesParse, Don't Validate episodeTiny steps help you prune the treeExploratory TestingWrap early, unwrap late
Ep 29029: Writing an elm-review Rule
dillonkearns/elm-review-html-to-elm (elm-review version of html-to-elm.com)Rule naming guidelines docsElm review cli new rule commandstil4m/elm-syntaxElm.Syntax.Rangeelm-review ignoreErrorsForFilesReview contextwithFinalModuleEvaluationelm-review's context is like Model, elm-syntax Node is like a Msg, Review Errors are Cmds, visitors are like updateelm-review's new configuration errors APIImport aliases feature: ModuleNameLookupTableParse, don't validate episodeelm-review Fixes APIJeroen's Safe Unsafe Operations blog postGetting startedSome repos to look at for inspirationgithub.com/jfmengels/elm-review-unusedgithub.com/jfmengels/elm-review-common github.com/jfmengels/elm-review-debug github.com/jfmengels/elm-review-simplify The elm-review package docs are very through and worth reading
Ep 28028: GitHub Actions
Continuous Integration (CI)CD (Continuous Delivery, Continuous Deployment)Mob programmingelm-program-test episodeCypress testing frameworkGH actions on events (schedule, workflow_dispatch, pull_request, etc.)elm-review new-packagenpm-run-allCan run npm-run-all test:*, but don't know the order it will run ingit hooksDependabotDillon's blog post about using dependabot for Elm dependenciesSend a tweet with a GH actionDillon's GH profile (and the GH action workflow for it)GH Action to include blog posts in profile feedGitHub's Octokit APICore GitHub Actions JavaScript packagesJavaScript GitHub Actions starter templateUnix toolchain philosophyelm-tooling-actionSimon Lydell's example GitHub Actions workflowGitHub Actions cache apiBrian Douglas' dev.to blog post seriesEdward Thomson's GitHub Actions advent calendar
Ep 27027: elm-tailwind-modules
Our guest: Philipp Krüger, aka matheus23 (github) (twitter)matheus23/elm-tailwind-moduleselm-reduce (Philipp's Bachelor's thesis)TailwindCSSThe Tailwind config fileelm-uiSass/ScssCSS inheritanceCohesion and coupling - don't separate things that need to be understood togethermonty5811/postcss-elm-tailwind paved the path for Philipp's libraryPurgeCSSPhilipp's library is a fork of justinrassier/postcss-elm-css-tailwindrtfeldman/elm-css (it's a drop-in replacement for elm/html)CSS in JSmiyamoen/elm-origamimatheus23/elm-default-tailwind-modules is the best way to start (it's the generated elm-tailwind-modules code for the default TailwindCSS configuration)elm-tailwind-modules currently requires you to order your breakpoints from high to low (see docs)tesk9/accessible-htmlgithub.com/dillonkearns/elm-pages-starterelm-pages-tailwind-starterCSS gridElm Radio elm-ui episodeminiBill/elm-ui-with-contextTailwindUI - a paid catalog of TailwindCSS templates and widgets/componentselm-ts-interop landing page (built with elm-tailwind-modules)html-to-elm.comelm-review rule for html-to-elm.com, dillonkearns/elm-review-html-to-elmRefactoring UI bookReact presentational components vs ???This blog post talks about the View Objects pattern in Object-Oriented ProgrammingElm Radio Incremental Steps episodeFullStack Radio podcastA FullStack episode about the TailwindCSS philosophyelm-css's fromUnstyled and toUnstyled are helpful for incremental adoption (start refactoring from the leaves)
Ep 26026: Funding Open Source with Evan Czaplicki
#PLTalk programming language panels#PLTalk panel discussion on fundingElm compiler roadmap documentelm-language-serverelm-format's abstract syntax tree output is in the brainstorming phaseelm-typescript-interop (the old approach)elm-ts-interop Elm Radio episode
Ep 25025: elm-ts-interop
elm-ts-interopNow-deprecated original library - elm-typescript-interopThe Importance of Ports - Elm Conf talk by Murphy RandleEvan's Vision for Data Interchange document recommends against implicit serialization. The deprecated elm-typescript-interop relied on Elm's automatic JSON serialization flags/ports. elm-ts-interop passes Json.Decode.Value's which is what the guide recommends.Blog post about TypeScript's Blind SpotsTypeScript discriminating unions are analagous to Elm custom typesTypes Without Borders Elm Conf talkelm-ts-json Elm pacakgeElm ts interop npm packageWhat's the source of truth?Nexus - code-first GraphQL servergraphql-js - schema-first GraphQLHasura and PostGraphile - Postgres schema is the source of truthElm Codecs episodeelm-ts-json Encode docsGetting StartedGet your discount code, and learn more about the Pro version, including the scaffolding tool and Pro CLI at elm-ts-interop.com.Two articles about the redesign of elm-ts-interop (originally published in Bekk's Functional Christmas posts)Combinators - Inverting Top-Down TransformsTypes Without Borders Isn't Enough
Ep 24024: elm-program-test
Aaron VonderHaar (github) (twitter)elm-format episodeelm-program-testelm-testelm-test episodeBDD As It's Meant To Be Done video by Matt WynneBDD (Behavior-Driven Development)Gherkin syntaxOutside in vs. inside out testingensure vs. expect functionsThe Effect PatternHttp simulation example from examples folderAn elm-program-test example using a generalized Effect typeelm-program-test GitHub issues for contributingThe Official elm-program-test GuidebookThe elm-test HTML querying API#testing channel in Elm SlackWriting Testable Elm keynote by Tessa Kelly
Ep 23023: elm-format
elm-formatprettiergofmt, the built-in Go formatting toolSome discussion of IntelliJ trailing whitespace issueselm-format editor integrations tableelm-toolingelm-tooling Elm Radio episodeJeroen's elm-format tips tweetNoExposingEverything ruleDiscussion about single-line conditionalsThe original Elm style guideJoin lines (J in vim, also available with intellij keybindings)
Ep 22022: elm-tooling with Simon Lydell
Simon Lydell (twitter) (github)elm-tooling-clielm-jsonInstall elm-tooling into your npm dev dependenciesnpxelm-publish-actionNPM's package.json scripts sectionNPM postinstall scriptsRichard's recommendation to use npm config set ignore-scripts true, which can cause issues because it also skips the postinstall from your package.jsonelm-tooling-cli docs websiteElm tooling in ciGitHub ActionsSimon's example GitHub Actions workflow with elm-toolingSeparate steps for Elm tooling install and npm install to optimize cachingnpm run --silent (or -s) to reduce noise (more ways to do it in this StackOverflow answer)npm test and npm start to run start and test from your package.json scriptselm-tooling quick start page
Ep 21021: elm-review Tips
The npx command runs NPM binaries from your shellSome tricks to easily try elm-review with no setup:npx elm-review --template jfmengels/elm-review-unused/example Init with a given template:npx elm-review init --template jfmengels/elm-review-unused/example Incremental adoptionDon't enable lots with errors, better to have few with no errorsEnable in CIignoreErrorsForFilesignoreErrorsForDirectoriesTry the --fix, --fix-all, and --watch flags (see how to run elm-review)Useful packages and workflowReview rule for Documentation.ReadmeLinksPointToCurrentVersionelm-verify-examplesSafe unsafe operations in Elm blog postelm-spa Elm Radio episodejfmengels/elm-review-debugjfmengels/elm-review-commonsparksp/elm-review-portssparksp/elm-review-importsGetting started with elm-review episodeIncremental Steps episode
Ep 20020: Holiday Special!
Our special guestsTessa Kelly (twitter) (github)Mario Rogic (twitter) (github)Matthew Griffith (twitter) (github)LinksLamderaRichard Feldman's talk Scaling Elm AppsLife of a File Elm Radio episode
Ep 19019: Scaling Elm Apps
Richard Feldman's talk Scaling Elm AppsLife of a File Elm Radio episodeWeb Components (can be used to encapsulate state heavy view components)How Elm Code Tends Towards SimplicityGOOS bookelm-spa framework
Ep 18018: Lighthouse Scores
Performance metricsFirst Contentful PaintTime to InteractiveCumulative Layout ShiftBest practicesLighthouse SEO AuditsLighthouse Best Practices AuditsPerformance best practicesCDNNetlifyImage OptimizationCloudinaryloading=lazySVGIconsApple touch and other icons to add to <head>Some resources on iconsWhat the apple touch icons meanGoogle web.dev resource on apple touch iconsmanifest.jsonPWAsProgressive Web AppsMust be HTTPSAbout service workersStale while revalidate service worker cache policyWorkboxelm-starterPerformanceElm optimization instructions for using Terser, the --opimize flag, and elm-optimize-level-2Dev tools performance tabJu Liu's article, Performant Elm, on analyze Elm performance using Chrome Dev ToolsHTTP2 Push is deadUsing preload tagsHere's an in-depth conference talk on different script tag techniques. Ishows the differences between different ways to load script tags, including using async, defer, and in HTML <head> vs. <body>SEOmeta viewport tagAxe accessibility toolsCanonical URLsOpenGraph tagsLighthouse accessibility auditsResourcesLighthouse netlify pluginweb.dev learn section
Ep 17017: Codecs
miniBill/elm-codec - JSON codec libraryMartinSStewart/elm-codec-bytesBackwards compatibilityelm-codec's FAQ section on backwards compatabilityMario Rogic's talk on Elm EvergreenMario Rogic's talk on LamderaKeeping data in syncElm Radio episode on elm-graphqlTwo Generals ProblemElm codec API - string, Bool, objectMartinSStewart/elm-serialize/latest/, encodes in a format that is optimized for compactness
Ep 16016: elm-graphql
dillonkearns/elm-graphqlElm Radio episode 4 - JSON decodersDillon's Elm Conf talk about the principles behind elm-graphql: Types Without BordersPhantom Typeselm-graphql's FAQ document Article about simple design in Elmelm-graphql Scalar Codecs tutorialHow can elm graphql decoding fail?SelectionSet.nonNullOrFailSelectionSet.mapOrFailCustom Scalars don't include type information, though there are some proposals for supporting optional type informationBackend Frameworks for Full-Stack GraphQL Type SafetyJuniper for RustHasura (database-schema based API)Postgraphile (database-schema based API)Discourse thread on differences between all the Elm graphql librariesharmboschloo/graphql-to-elm - library for generating Elm functions to make queries from GraphQL strings
Ep 15015: Incremental Steps
Dillon's Elm Europe talk Incremental Type Driven DevelopmentTest driven developmentFake it till you make itelm-markdown GitHub-Flavored Markdown table live streamSucceed is the key to successPractical refactoring with Llewllyn Falco and Woody ZuillLlewllyn Falco doing Gilded Rose kata with TCR and snapshot testingDillon's article on Relentless, Tiny Habits
Ep 14014: The Life of a File
Evan Czaplicki's talk The Life of a File.Richard Feldman's Frontend Masters Elm coursesExplore many different data modeling optionsMake Impossible States Impossible Elm Radio episodeWait until you feel the pain vs create abstractions before you need themDoes the code quality metric of line count apply in Elm since there's no spooky action at a distanceAim for loose coupling, high cohesionLocalized reasoningCore mechanics of Elm modules(Organize) Grouping functions values types(Hide) You can hide some of those things. Allows encapsulation, shielding from breaking changes, avoiding coupling.Create modules around domain conceptsUse ubiquitous languageGiant update functionsYou can think of the update function as a delegator - get things to the right place rather than doing the work itselfelm-reviewTCC (test && commit || revert)What are you gaining from extracting a module?Protecting invariantsHiding internalsDecouplingTDD helps drive module design.Experiment, but review your experiments before they become deeply ingrained.Pain in code is for sending a message.Technical debt isn't about "clean code". It's abstractions that serve what the code is doing. Abstractions are inherently expensive and a type of tech debt if they don't serve a purpose for your specific needs.Be proactive - immediately as soon as there is a clear way to make code better (not perfect, small improvement) - do itRelentless, Tiny Habitselm-test Elm Radio episodeTesting is helpful for identifying modules - see keystone testing habit blog postProperty based testing is a sign that something is a module - it has a clear property, which means you want to protect the internalsIt's okay to get it wrong, just don't get it all wrong up front with premature abstractions.
Ep 13013: Make Impossible States Impossible
The talksMake Impossible States Impossible from Elm Conf 2016Make Data Structures from Elm Europe 2018Elm Radio Episode 2: Intro to Opaque TypesDealing with Impossible StatesBuilding up a "truth table" of possible states (see Evan's guide Types as Sets)Which rows are invalid?Create a new type with only the valid ones possibleMore referenceselm-cssTereza's line-charts packageTereza's elm Europe talkelm-graphqlGilded rose live streamSnapshot testing (also called Approval Tests)Jeremy Fairbank's Boolean Blindness talk
Ep 12012: elm-spa
elm-spaRichard Feldman's elm-spa-example GitHub repoElm's Browser.applicationUrl.Parser - URL parsing in Elm for routing single-page appselm-shared-state pattern (formerly called elm-taco)Next.js and NuxtJSRouting and dynamic routing in elm-spaScaling Elm Apps talk - Elm Europe keynote by Richard FeldmanGetting Started ResourcesOffical elm-spa Guide#elm-spa-users channel on the official Elm slackelm-spa-realworld (Ryan's version of elm-spa-example using his elm-spa framework)Exploring elm-spa example - Richard's conference talk walking through codebaseRichard's Frontend Masters courses focus heavily on his elm-spa-example repoElm Radio Episode 7: Extending Elm
Ep 11011: Parse, Don't Validate
Alexis King's article Parse, Don't Validatethe difference between validation and parsing lies almost entirely in how information is preservedShotgun parsing (original academic paper)Mixing processing and validating dataShotgun parsing is a programming antipattern whereby parsing and input-validating code is mixed with and spread across processing code—throwing a cloud of checks at the input, and hoping, without any systematic justification, that one or another would catch all the “bad” cases.Why the term "parse"?a parser is just a function that consumes less-structured input and produces more-structured output [...] some values in the domain do not correspond to any value in the range—so all parsers must have some notion of failureConditionally return typesDon't have to repeatedly check conditionLook out for "lowest common denominator" built-in values being passed around (like empty String)Maybe.withDefault might indicate an opportunity to parseTwo ways to use this technique:Weaken return typeStrengthen input typeDesign by contractElm Radio JSON decoders episode
Ep 10010: elm-test
elm-test Basicselm-test NPM packageelm-explorations/test Elm packageelm-test init commandRunning elm-test finds exposed values of type TestTDD PrinciplesTesting in Elm is easier because it's just expectations of input to output (deterministic)TDD is a design practice tooProgramming by IntentionWriting test first makes code testable & decoupledRed, green, refactorYAGNI"Make the change easy, then make the easy change"Kent Beck's TDD by ExampleHere's a staring template of a code kata in Elm that you can use to practiceEmily Bache has many more code katas you can practice on her GitHubFuzz TestingAlso known as Property-Based TestingMartin Janiczek's elm-minithesis projectelm-test's view testing API includes Test.Html.Query, Test.Html.Selector, and Test.Html.Event View objectsTesting pyramidMocking and stubbing are not needed or possible in ElmOrder dependent test helper in Ruby: i_suck_and_my_tests_are_order_dependentWhen to Use Types or TestsJeroen's Safe Unsafe Operations blog postRichard Feldman's talk on Types and TestsMake Impossible StatesShould you test implementation details?Discourse thread discussing testing internalsThink in terms of a modules responsibilityHigher-Level Testing in Elmelm-program-test Martin Janiczek's elm Europe talk on testing Msg's with ArchitectureTestRichard test-update package
Ep 9009: elm-ui
elm-ui packageFewer overlapping ways to express viewsElement.padding (no concept of margin)Previously called style-elementsThere used to be a notion of a single type defining all possible stylesLatest elm-ui simplifies that by using only inline styles. You build your own abstractions with vanilla Elm functions/modules etc.Element type is the equivalent of the Html type from elm/htmlelm-css packageMobster appEscape hatchesElement.html works at leaf nodes, but elm-ui in general doesn’t mix with plain htmlElement.htmlAttributeRefactoring is a huge asset for a team, so much easier than css refactoringDoesn’t expose all the css tricks directly, sometimes you need escape hatches to access thoseResponsivenessPass in window size from your Elm modelDoesn’t use media queries, so that approach doesn't play well with with pre-rendered html like in elm-pagesclassifyDevice is an optional helper for responsivenessSemantic htmlExpress layout with Element.row, column, elSemantic HTML is independent from layout. Set with attributes using the Element.Region module.WrappingElement.paragraph uses text wrappingem/remelm-ui doesn't expose access to rem and em units to simplify the mental model and reduce overlapping ways to express somethingCookbooks/examplesLucas Payr's elm-ui-widgets Alex Korban's elm-ui patterns )Debugging elm-ui viewsElement.explain gives you highlights around nested elementsInspecting developer tools doesn't help much with elm-ui, but elm-ui is much more traceable because it doesn't have layout cascading like CSSResourcesMatt's elm-ui announcement talk at Elm Europe (was about elm-style-elements, but still worth a watch)Matt's more recent elm-ui conference talkRichard Feldman's talk CSS as Bytecode (uses style-elements, but it's a great intro tutorial on elm-ui concepts)#elm-ui channel in the Elm slack
Ep 8008: The Builder Pattern
What is a Builder?Init a builder data structure with a set of reasonable defaultsCustomize those defaults through a series of chained function callsBuilders have the same type for the return type and final argument, so that they work nicely in a pipelineResources and ExamplesLuke Westby's http-builder packageBrian Hicks' Robot Buttons from Mars talkelm-review package docselm-pages/phantom builder live codingRichard Feldman's Oslo Elm Days keynote
Ep 7007: Extending Elm
Platform.workerWhat can you do with Elm?HtmlHttpPortsWeb ComponentsDifferent techniques for extending elmelm-pages StaticHttp APIElm radio episode 1 on elm pageselm-graphqlCodegenMacrosElixir exunitWrapper elm appsCan emulate effect managersPlatform.workerIntrospectionelm-typescript-interopPorts and flagsWeb ComponentsCode transformationElm asset loader webpackHacking JS to get FFIDepending on internal details could end up with broken codeelm-hot and elm-hot-webpack-loaderPitfalls and considerationsCodegenHave a single clear source of truth for codegenPrevent bad states with airtight abstractions, rather than having lots of caveatsMake sure public APIs for generated code look niceUse doc commentsMacrosElm code that doesn’t look like elm codeTooling doesn’t work then - see Babel ecosystemViolates Open close principle - you’re modifying the language, not extending itProvide a platform with extensions in mind when you build tools so you don’t require users to hackWhen you build a tool, think about the mental model for uses, let that guide you. Avoid leaky abstractionsBe opinionated about the core things, and unopionated about what’s not essential to the tool[elm-spa](https://github.com/ryannhg/elm-spa)
Ep 6006: elm/parser
What is a parser?yacc/lexAST (Abstract Syntax Tree) vs. CST (Concrete Syntax Tree)JSON decoding vs. parsingJSON decoding is validating a data structure that has already been parsed. Assumes a valid structure.elm/parserHaskell parsec library - initially used for the Elm compiler, now uses custom parserWhat is a parser?One character at a timeTakes input string, turns it into structued data (or error)ComittingBacktrackable parserschompIf and chompWhileParser.oneOfBenchmarkingelm-explorations/benchmarkBenchmark before making assumptions about where performance bottlenecks areWrite unit tests for your parserGFM table parsing live streamParser.succeedElm regex vs elm parserIndications that you might be better off with parserLots of regex capture groupsWant very precise error messagesGetting source code locationsParser.getRow and getColParser.getSourceParser.loopLoop docs in elm/parserLooping allows you to track state and parse groups of expressionsLoop over repeated expression type, tell it termination condition with Step type (Loop and Done)Error MessagesYou can fail with Parser.problemParser.Advanced module is designed to give you more precise context and error messages on failureParser.Advanced.inContextGetting Started with a Parser ProjectWrite lots of unit tests with elm-test!There's likely a specification doc if you're parsing a language or formal syntaxCommonMark SpecGitHub-Flavored Markdown Specdillonkearns/elm-markdown test results directory from executing spec examplesLook at examples of parser projectsdillonkearns/elm-markdownelm-in-elm parserelm-in-elm conference talkmdgriffith/elm-markup - good reference for parsing, fault-tolerant parsing, and giving nice error messagesTereza's YAML parserTereza's elm conf talk "Demystifying Parsers"Jeroen's elm/parser Ellie"It's not hacking if you have tests."Look at elm/parser docs and resourceselm/parser project's semantics document describes backtrackable behavior in detail
Ep 5005: How (And When) to Publish a Package
What is an Elm Package?Elm package repositoryElm packages enforce SemVer for the public package APIThe SemVer (Semantic Versioning) SpecInteresting note: the SemVer spec says breaking changes only refers to the public API. But a core contributor clarifies that breaking changes can come from changes to the public contract that you intend users to depend on. See this GitHub thread.list-extra packagedict-extra packageMinimize dependencies in your package to make it easier for users to manage their dependencies"Vendoring" elm packages (using a local copy instead of doing elm install author/package-name) can be useful in some cases to remove a dependency from your packageShould you publish a package?The Elm package ecosystem has a high signal to noise ratioElm packages always start at version 1.0.0SemVer has different semantics before 1.0.0 (patch releases can be breaking before 1) - see SemVer spec item 4Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.Elm package philosophy is to do an alpha phase before publishing packageKeep yourself honest about solving meaningful problemsStart by asking "What problem are you solving? Who are you solving it for?"Scratch your own itchelm-graphqlservant-elm (for Haskell servant)Keep yourself honest about solving problems by starting with an examples/ folderEarly elm-graphql commits started with examples before anything elseWrite meaningful test cases with elm-testelm-verify-examplesHave a clear visionAsk people for feedbackLet ease of explanation guide you to refine core conceptsMake it easy for people to understand your package goals and philosophyInclude code examples in readme and docs to make it easier for people to get startedelm-review live stream videoUse meaningful examples solving concrete problems (images/screenshots are good, too)Richard Feldman's Exploring elm-spa-example talkLuke's elm-http-builder packageelm-spa-example's custom http request builder moduleInstead of writing a package, in some cases it could make sense to publish a blog post to share a patternPorting libraries vs. Coming Up With an Idiomatic Solution for ElmInstead of moment js ported to Elm, have an API built for a typed contextRyan's date-format packageHow to design an Elm package APIDefine your constraints/guarantees, make impossible states impossibleCharlie Koster's Advanced Types in Elm blog post seriesAvoid exposing internals of your dataElm Radio episode 002: Intro to Opaque TypesPay attention to how other packages solve problemsRichard Feldman's talk The Design Evolution of elm-css and elm-testBrian Hicks' talk Let's publish nice packagesLook at prior art, including in other ecosystemsLook at github issues and blog posts from projects in other ecosystemsPick your constraints instead of trying to solve every problemHelps you choose between tradeoffsHaving clear project goals explicitly in your Readme makes it easier to discuss tradeoffs with users and set expectationsIdiomatic elm package guide has lots of info on basic mechanics and best practices for publishing Elm packagesThe mechanics of publishing an elm packageelm make --docs docs.json will tell you if you're missing docs or if there are documentation validation errorselm-doc-previewCan use elm-doc-preview site to share documentation of branches, or packages that haven't been published yetSet up a CIDillon's CI script for dillonkearns/elm-markdown packageDillon's elm-publish-action GitHub Action will publish package versions when you increment the version in your elm.json - nice because it runs CI checks before finalizing a new package releaseelm publish will walk you through the steps you need before publishing the first version of your Elm package#packages channel on the Elm slack shows a feed of packages as they're published#api-design channel on the Elm slack is a good place to ask for feedback on your API design and package ideaContinue the ConversationShare your package ideas with us @elmradiopodcast on Twitter!
Ep 4004: JSON Decoders
Basicselm/json package docsElm Guide section on JSON DecodersValidates that data has the expected shape. Similar to the pattern we discussed in episode 002 Intro to Opaque Types.Ports and FlagsHere's an Ellie example that shows the error when you have an implicit type that your flags decode to and it's incorrect.Sorry Dillon... Jeroen won the trivia challenge this time 😉 It turns out that ports will throw exceptions when they are given a bad value from JavaScript, but it doesn't bring down your Elm app. Elm continues to run with an unhandled exception. Here's an Ellie example.Flags and ports will never throw a runtime exception in your Elm app if you always use Json.Decode.Values and Json.Encode.Values for them and handle unexpected cases. Flags and ports are the one place that Elm lets you make unsafe assumptions about JSON data.Benefits of Elm's Approach to JSONBad data won't end up deep in your application logic where it's hard to debug (and discover in the first place)Decouples serialization format from your Elm data typesYou can do data transformations locally as you build up your decoder, rather than passing your giant data structure through a single transform functionDecoding Into Ideal TypesRichard Feldman's elm-iso8601 packageelm/time packageProgramming by intentionJson.Decode.succeed is helpful for stubbing out dataDillon's Incremental Type Driven Design talk at elm EuropeJson.Decode.fail lets you validate data and fail your whole decoder if there’s a problemParse, don’t validate blog post by Alexis KingDillon's elm-cli-options-parser packageJson.Decode.maybe docsNote about Decode.maybe. It can be unsafe to use this function because it can cover up failures. Json.Decode.maybe will cover up some cases that you may not have intended to. For example, if an API returns a float we would suddenly get Nothing back, but we probably want a decoding failure here:import Json.Decode as Decode """ {"temperatureInF": 86} """ |> Decode.decodeString (Decode.maybe (Decode.field "temperatureInF" Decode.int)) --> Ok (Just 86) """ {"temperatureInF": 86.14} """ |> Decode.decodeString (Decode.maybe (Decode.field "temperatureInF" Decode.int)) --> Ok Nothing Json.Decode.Extra.optionalNullableField might have more intuitive and desirable behavior for these cases.Thank you to lydell for the tip! See the discussion in this discourse thread.Learning resourceBrian Hicks' book The JSON Survival KitJoël Quenneville’s Blog Posts About JSON DecodersGetting Unstuck with Elm JSON Decoders5 Common JSON DecodersElm's Universal PatternGuaranteeing that json is valid before runtimeelm-graphql packageThe basics of GraphQLDillon's Types Without Borders Elm Conf talkElm Radio 001 Getting Started with elm-pageselm-pages StaticHttp API docsKris Jenkins' elm-export tool for Haskell types to Elm.Mario Rogic's Evergreen Elm elm Europe talkAutogenerating json decodersjson-to-elm tool - generates Elm decoders from raw JSON valuesintellij-elm JSON decoder generatorOrganizing your decodersEvan Czaplicki's elm Europe keynote The life of a fileEvan's experience report on implicit decoding in HaskellGetting StartedUnderstand Json.Decode.mapUnderstand record type aliases - the function that comes from defining type alias Album = { ... }Submit your question to Elm Radio!
Ep 3003: Getting started with elm-review
elm-reviewreview-rgb-ranges package by RunarElm Analyseelm-review 1.0 release announcement blog postelm-review 2.0 release announcement blog postCustom Scalars in elm-graphql
Ep 2002: Intro to Opaque Types
Opaque TypesSome patternsRuntime validations - conditionally return type, wrapped in Result or MaybeGuarantee constraints through the exposed API of the module (like PositiveInteger or AuthToken examples)Package-Opaque ModulesExample - the Element type in elm-ui.Definition of the Element type aliaselm-ui's elm.json file does not expose the internal module where the real Element type is defined.Example from elm-graphql codebase - CamelCaseName opaque type
Ep 1001: Getting started with elm-pages
elm-pages hydrates into a full Elm app. It solves similar problems to what GatsbyJS solves in the ReactJS ecosystem.Static site generators with JS-free outputhttps://korban.net/elm/elmstatic/https://jekyllrb.com/EleventyMeta TagsOpen Graph tagsAsset management with elm-pages (CSS vs. SASS,etc.)Github issue discussing using the Unix Toolchain Philosophy in the context of keeping elm-pages focused on primitive assets for elm appsCompared to extending the Gatsby webpack configSOLID Open-Closed Principleelm-pages showcaseChandu's art showcase (built with elm-pages) - https://tennety.art/Headless CMSes vs. monolothic site providershttps://www.sanity.io/contentful.comhttps://airtable.com/netlifycms.orgCDN hosting provider NetlifyStatic Site Generators and The JAMstackhttps://jekyllrb.com/ - static site builder in Ruby - perhaps the first static site generator?Eleventy - spritual successor to Jekyll - but more flexibleMore info on what exactly is the JAMstack?Getting started with elm-pageselm-pages-starter repoelm-pages vs. elm/browserPages.Platform.applicationThe elm-pages StaticHttp APIStaticHttp Docs (there's a description of when and why you would use this compared to elm/http)elm-pages.com blog post A is for API - talks about StaticHttp and its lifecycle, including some example code.Core ConceptsSEO - elm-pages SEO API docsSecrets - docsSection in StaticHttp blog post about how you don't use Msgs for your StaticHttp datagenerateFiles hookIncremental Elm Live - Twitch streaming seriesWhere to learn moreelm-pages.comJoin the Elm slack and say hello in the elm-pages channel!