elm-landelm-review-unusedelm-pkg-js specelm-pages scripts episodeOptimizedDecoder in elm-pages v2elm-pages v3 Express community adapterdillonkearns/elm-form episodeelm-pages v3 announcement postelm-uielm-tailwind-moduleselm-formatlamdera/program-testelm-review docselm-doc-previewelm-review-documentationelm-verify-examplessparksp/elm-review-forbidden-wordselm-package-starterelm-bookvendrinc/elm-gqldillonkearns/elm-graphqlelm-codegenremotedata packageelm-graphql episodeharmboschloo/graphql-to-elmdtwrks/elm-bookmethod_missingelm-spaelm-spa-realworld exampleelm-codegenelm-codegenelm-syntaxelm-syntax-dslelm-uiElm.Type.Type from elm/project-metadata-utils represents all possible Elm typeselm-codegen announcement post on Discourseelm-codegen repoklazuka/elm-hotSponsor: CareRev
CareRev is looking for Senior Frontend Elm engineers (job listing).
elm-review-simplifyelm-snapshot-test prototype repoelm-coverageelm-instrumentelm-coveragesparksp/elm-review-imports either new feature, or separate project to give suggestions to make all inconsistent imports in a project consistentelm-review code actionselm-review collection mechanism to gather data from an ASTelm-graphql but with factory-style API for mocking out data that is compliant to the graph schema, for use with things like elm-program-testBrowser.application wrapper that provides some common initial flags like start time, initial window dimensions etcHttpError type defined in elm-graphql)elm-color packageelm-format in Elmelm diff, but it gives you more detailed information about code changes even if they don't change the APIelm-reviewelm-http-fusion to gather better type incormation about an APIelm-http-fusion embeddable in the elm-pages dev server so you can interactively fix decoder errors, etc.elm-codegen for elm-pages scaffolding for user-customizable templateselm-css tool to make inline styles into static CSS files and replace the styles with a reference to the generated class. Goal: reduce bundle size and performance overheadelm-review fixes in a hidden temp directoryelm/parser debugger to see the state machine of what has been consumedCmds in the debugger, or similar idea for debugging elm-pages DataSources to see why a failure happened and what the breadcrumbs areink, but for Elmawesome-elm-sponsorship repoarray-callback-return ESLint ruleelm-test episodeFuzz.andThen and Fuzz.filter (existed in 0.18 but were removed because they didn't shrink well)#testing channel on the Elm Slacketaque/elm-formelm-codecelm-fetch packageRemoteData packageelm-program-test is useful for integration testing data loadingelm-suspense proof-of-concept repodataRequestselm-bookelm-book)elm-verify-exampleselm-charts siteelm-widgets (alpha package docs)elm-admin (alpha package docs)elm-ui-explorer (alternative Elm storybook style framework - comes with knobs)dmy's githubelm-graphql selection set docs page (reads like a tutorial top to bottom)<input> tagssparksp/elm-review-no-forbidden-wordselm-verify-exampleselm-review-unused elm-review ruleelm-review-simplifyelm-review-unused with elm-review --template jfmengels/elm-review-unused/exampleList.concatMap is the same pattern as andThen under a different nameandThen identity can be used to flatten somethingelm-list-cartesian package gives two valid map2 implementions for Listelm-review-simplify packageMore of Joël's distillation of category theory ideas:
ianmackenzie/elm-units packageavh4/elm-program-testelm-community/js-integration-exampleselm-optimize-level-2Html.Lazy APIProcess.elm comment about the potential for parallelizing workJson.Decode.maybe is almost never what you intendWhere Could We Turn Up the Good?Pure FP* Elm 0.19 removing side effects
* Purity is what makes elm-review interesting
* Jeroen's post Safe dead code removal in a pure functional language
* No runtime exceptions
Useful Error MessagesUseful error messages
Having a single language flavor* Isomorphic code
* Meta frameworks (elm-pages, Lamdera, elm-spa)
Decoupled tools* The community can iterate quickly and experiment with new changes
* elm-optimize-level-2 and elm-format are great examples
* elm-optimize-level-2 can make their way upstream and don't break Elm's guarantees or assumptions
* Robin Hansen's blog post series Successes, and failures, in optimizing Elm’s runtime performance
* Extensible Web Manifesto
* Platform should provide building blocks, not solve every specific use case
Stable Core* Stable data layer, architecture allows ecosystem to evolve around it with less churn
Community Members Working on What They're Passionate About* People passionate about a problem working on it in the ecosystem
Performance* Leveraging Elm's unique characteristics for performance (immutability, static language, known types, etc.) * Elm compiler performance - compiler speed matters
Content and Conferences* Elm community content and conferences * Elm Online meetdown
The Elm Philosophy* Evan's Elm philosophy tweet * Philosophy has influenced package design in the ecosystem * Elm Slack #api-design channel
Our special guests* Ryan Haskell-Glatz (twitter) (github) * Brian Hicks (twitter) (github) * Robin Heggelund Hansen (twitter) (github)
Ideas for Effective Learning Have a playground to try out ideas * Try a new tool or technique with a familiar problem or exercise * Small scale exercises and real world projects * Small scale exercises are helpful for quickly developing a skill * Feedback loops * Tiny steps shorten the feedback loop * Use code katas like bowling, tennis, roman numeral katas * Analogous to empirical scientific method (hypothesis, test, analyze) * Call your shot * Don't forget to analyze test results after * Listen to smart people, but come to your own conclusions * Try two alternate ways of doing something out for yourself * Failure is part of learning * Follow your curiosity * Look at the source for projects you depend on or come across * Growth Mindset vs. Fixed Mindset * You have to make knowledge your own (synthesis) - connect it to what you know * Just in time vs. just in case learning - focus on what you need or seems important now * Flexbox Froggy game * Demystify things (for example custom type constructors vs type alias constructors) * Mind mapping * Elm Radio Opaque Types episode * Zettlekasten second brain * How to Take Smart Notes book * Make declarative statements in second brain system * Dillon's use the platform note from his digital garden * Digital gardening * Learn in public movement * Richard Feldman's talk Scaling Elm Apps * Richard experimenting with dream writer in a component architect * Make It Stick book (and some notes summarizing key ideas) * Elm Radio API Design Lessons episode * Let your background processing do some work for you * Dan Pink's book When* * Early bird vs night owl thinking * Jeroen's blog
Guest: Andrey Kuzmin (github) (twitter)
elm-explorations/webglelm-explorations/linear-algebra/latestelm-3d-scene exampleselm-webgl-playground examplesany typeTypeScript's any vs. Elm's Debug.todoTypeScript's any essentially "turns off" type checking in areas that any passes through.
In Elm:
Debug.todo, but you can't build your app with --optimize if it has Debug.todo's in itThis 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 ElmnoImplicitAny+ object, '' + {} === '[object Object]')any regardless of implementation if they aren't given an explicit typenumber values instead of literal typeselm-ts-interopdillonkearns/elm-markdown1 interrupt paragrpahs, starting with other numbers don'tdillonkearns/elm-markdown's Core Tools for Extensibility* Custom Renderers
* Html handlers (example)
* Transforming parsed Markdown Blocks (AST)
* incrementalelm.com code for getting back references from parsed markdown
* Jeroen's Hierarchy of Constraints note
* Helpers for folding over Blocks and Inlines
* Extracting table of contents example
* Discussion to formalize HTML parsing and error handling spec in dillonkearns/elm-markdown
* Example of unintuitive raw HTML tag handling in markdown: <span> closed by whitespace (ignores closing tag)
* Zettlekasten
* Wikilinks
* Foam Research
* GFM Autolinks extension
* elm-explorations/markdown
* Matthew Griffith's elm-markup package
* Matt's Oslo talk on fault tolerant parsing A Markup for the Statically Typed
* elm-optimize-level-2
* Shiki
* Deckset
* UnifiedJS markdown transformation ecosystem
* elm-markdown-transforms
* Render to a function (example)
* Scheme evaluator example (demo) (code)
* elm-pages 2.0 episode
* Markdown announcement blog post Extensible Markdown Parsing in Pure Elm
* #markdown channel in The Elm Slack
* Example of extracting title and description from parsed markdown
* Elm Online Meetdown
* Submit a talk proposal to the Elm Online Call for Speakers form
ianmackenzie/elm-unitselm-graphql SelectionSet scope type variablewith functionselm-review Rule API uses phantom builderPossible operations with phantom extensible builders* Add a new field * Remove a field * Change the type of a field * Remove the previously existing phantom type and change it to an empty record (not extensible, just a hardcoded return type) i.e. Replace
What you can do with phantom builder* Require something to be always called * Forbid something being called more than once * Cause other constraints dynamically after calling something * Make function calls mutually exclusive * Enable a function only if another one has been called
terezka/elm-chartsline-charts and elm-plotgampleman/elm-visualizationelm-vegaLamdera is about removing non-essential complexity - 6 concepts
elm-pkg-js specelm-webappelm-review-performanceHtml.LazyList.map will return a list with a new reference, for example.bcp-47-language-tag packageelm-optimize-level-2elm-explorations/benchmarkgatherWith isInfixOfelm-pages v2!elm-pages has a build stepDataSource.FileDataSource.failDataSource.GlobDataSource.distillCodecelm-graphql DataSource example from incrementalelm.comelm-spa V5 Docselm-spa v5 episodeKey new features in v6Protected pages
elm-program-test docs siteelm-spaelm-pages 2.0 routing and splat routeselm-spa add commandelm-liveelm-spa View moduleelm-spa v6 has an ejectable Effect moduleelm-real-world SPA example (elm-spa-example using elm-spa framework)elm-program-test example folder#elm-spa-users channel on the Elm Slackdillonkearns/elm-package-starterLessons1. Avoid unexpected or silent behavior 2. Give context/feedback when things go wrong so the user knows their change was registered, to enhance trust 3. Good errors aren't just for beginners - Curb Cut Effect 4. Sandi metz - code has a tendency to be duplicated - be a good role model - we're influenced by precedence 5. Matt Griffith - API design is holistic. It's a problem domain. Rethink from the ground up. 6. Learn from the domain and terms, but don't limit yourself to it when you can create better abstractions. 7. 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. 8. 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 Picture 9. API design is a tool to help you solve problems. 10. There's a qualitative difference when you wire up feedback before you up front. 11. Avoid toy examples, use meaningful use cases to direct your design. 12. 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. 13. Come up with an API with the most benefits and the least pain points. 14. If there's something that you want to make really good, invest in giving it a good feedback mechanism. 15. 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. 16. 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. 17. Have a clear message/purpose - whether it's an API, or an internal module. 18. Take responsibility for user experiences.
prefers-reduced-motion media querytesk9/accessible-htmllist-style-image in CSSelm-css - tesk9/accessible-html-with-cssmap2Maybe.map2MetaphorsSome common metaphors for Elm's Universal Pattern (Applicative Pattern).
Examples* Random generators * Apply mapping functions to vanilla value functions to keep things clean
Tips* Separate branching code from doing code (discussed in-depth in Joël's blog post Problem Solving with Maybe)
* Stay at one level of abstraction
* Json decoders as combining functions
* Scott Wlaschin Railway Oriented Programming
* Dillon's blog post Combinators - Inverting Top-Down Transforms
* The JSON structure and Elm type don't have to mirror each other - start with your ideal type and work backwards
* Applicative pattern
* Applicative needs 1) way to construct, 2) map2 or andMap
* Json.Decode.Pipeline.required function
Record constructors* Practice writing it with an anonymous function to convince yourself it's equivalent
* Record constructors are just a plain old elm function
* map2 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 own
* Applicative Laws in Haskell
* Monomorphic vs polymorphic
* Parser Combinators
* elm/parser episode
* Joël's blog posts on the ThoughtBot blog
* Joël's Random generators talk
* Joël's Maybe talk
Some more blog posts by Joël that related to Elm's Universal Pattern:
Joël's journey to building a parser combinator:
elm-graphqldillonkearns/elm-graphqlWatchers for rerunning codegen* Rerun code gen when the source of truth changes ideally
* Chokidar CLI
* The Design of Everyday Things by Donald Norman
* Affordances
* Mappings
* elm-tailwind-modules
* Chadtech/elm-vector
* the-sett/salix
* elm-ts-interop
Scaffolding* elm-review init, new-rule, and new-package
* elm-spa new
* html-to-elm.com
* End to end testing your generated code
* Snapshot testing
* elm-graphql's snapshot testing script
* html-to-elm.com generated test suite
* elm-verify-examples
Elm Debugging techniques* Debug.todo
* Frame then fill in
* Annotation let bindings
* Using nonsense names as a step
* Elm review rule to check for nonsense name
Hardcoded values vs debug.todo* Todos don't allow you to get feedback by running your code * TDD * Fake it till you make it * Simplest thing that could possibly work * Joël Quenneville's article Classical Reasoning and Debugging * Debugging is like pruning a tree
Breaks* Take a walk. Step away from the keyboard when you're grinding on a problem
* sscce.org (Short, Self Contained, Correct (Compilable), Example)
* Create a smaller reproduction of the problem
* Reduce the variables, you reduce the noise and get more useful feedback
* Reasoning by analogy from Joël's post
* Elm debug log browser extension
* node --inspect
* elm-test-rs
Debug.log in unit tests* Test.only for running just one test or describe
* Put Debug.logs in each path of an if or case expression
* Use the browser elm debugger to inspect the model
* Scaling Elm Application episode
* Narrow down your search space with Elm types
* Parse, Don't Validate episode
* Tiny steps help you prune the tree
* Exploratory Testing
* Wrap early, unwrap late
dillonkearns/elm-review-html-to-elm (elm-review version of html-to-elm.com)Elm.Syntax.Rangeelm-review ignoreErrorsForFileswithFinalModuleEvaluationelm-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 APIModuleNameLookupTableelm-review Fixes APIGetting startedSome repos to look at for inspiration
The elm-review package docs are very through and worth reading
elm-program-test episodeon events (schedule, workflow_dispatch, pull_request, etc.)elm-review new-packagenpm-run-all test:*, but don't know the order it will run inmatheus23 (github) (twitter)matheus23/elm-tailwind-moduleselm-reduce (Philipp's Bachelor's thesis)elm-uimonty5811/postcss-elm-tailwind paved the path for Philipp's libraryjustinrassier/postcss-elm-css-tailwindrtfeldman/elm-css (it's a drop-in replacement for elm/html)miyamoen/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-starterelm-ui episodeminiBill/elm-ui-with-contextelm-ts-interop landing page (built with elm-tailwind-modules)dillonkearns/elm-review-html-to-elmelm-css's fromUnstyled and toUnstyled are helpful for incremental adoption (start refactoring from the leaves)elm-language-serverelm-format's abstract syntax tree output is in the brainstorming phaseelm-typescript-interop (the old approach)elm-ts-interop Elm Radio episodeelm-ts-interopelm-typescript-interopelm-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.elm-ts-json Elm pacakgeWhat's the source of truth?* Nexus - code-first GraphQL server
* graphql-js - schema-first GraphQL
* Hasura and PostGraphile - Postgres schema is the source of truth
* Elm Codecs episode
* elm-ts-json Encode docs
Getting Started* Get 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)
elm-format episodeelm-program-testelm-testelm-test episodeensure vs. expect functionselm-program-test example using a generalized Effect typeelm-program-test Guidebookelm-test HTML querying API#testing channel in Elm Slackelm-formatprettiergofmt, the built-in Go formatting toolelm-format editor integrations tableelm-toolingelm-tooling Elm Radio episodeelm-format tips tweetNoExposingEverything ruleJ in vim, also available with intellij keybindings)elm-tooling-clielm-jsonnpxelm-publish-actionscripts sectionpostinstall scriptsnpm 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 ci* GitHub Actions
* Simon's example GitHub Actions workflow with elm-tooling
* Separate steps for Elm tooling install and npm install to optimize caching
* npm 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 scripts
* elm-tooling quick start page
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 adoption* Don't enable lots with errors, better to have few with no errors
* Enable in CI
*ignoreErrorsForFiles*ignoreErrorsForDirectories* Try the--fix,--fix-all, and--watch` flags (see how to run elm-review)
Useful packages and workflow* Review rule for Documentation.ReadmeLinksPointToCurrentVersion
* elm-verify-examples
* Safe unsafe operations in Elm blog post
* elm-spa Elm Radio episode
* jfmengels/elm-review-debug
* jfmengels/elm-review-common
* sparksp/elm-review-ports
* sparksp/elm-review-imports
* Getting started with elm-review episode
* Incremental Steps episode
Our special guests* Tessa Kelly (twitter) (github) * Mario Rogic (twitter) (github) * Matthew Griffith (twitter) (github)
Links* Lamdera * Richard Feldman's talk Scaling Elm Apps * Life of a File Elm Radio episode
Performance metrics* First Contentful Paint * Time to Interactive * Cumulative Layout Shift
Best practices* Lighthouse SEO Audits * Lighthouse Best Practices Audits
Performance best practices* CDN * Netlify
Image Optimization* Cloudinary * loading=lazy * SVG
Icons* Apple touch and other icons to add to <head>
* Some resources on icons
* What the apple touch icons mean
* Google web.dev resource on apple touch icons
* manifest.json
PWAs* Progressive Web Apps * Must be HTTPS * About service workers * Stale while revalidate service worker cache policy * Workbox * elm-starter
Performance* Elm optimization instructions for using Terser, the --opimize flag, and elm-optimize-level-2
* Dev tools performance tab
* Ju Liu's article, Performant Elm, on analyze Elm performance using Chrome Dev Tools
* HTTP2 Push is dead
* Using preload tags
* Here'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>
SEO* meta viewport tag * Axe accessibility tools * Canonical URLs * OpenGraph tags * Lighthouse accessibility audits
Resources* Lighthouse netlify plugin * web.dev learn section
miniBill/elm-codec - JSON codec libraryMartinSStewart/elm-codec-bytesBackwards compatibility* elm-codec's FAQ section on backwards compatability * Mario Rogic's talk on Elm Evergreen * Mario Rogic's talk on Lamdera
Keeping data in sync* Elm Radio episode on elm-graphql * Two Generals Problem
Elm codec API - string, Bool, object
MartinSStewart/elm-serialize/latest/, encodes in a format that is optimized for compactnessdillonkearns/elm-graphqlelm-graphql's FAQ document
Article about simple design in ElmHow can elm graphql decoding fail?* SelectionSet.nonNullOrFail
* SelectionSet.mapOrFail
* Custom Scalars don't include type information, though there are some proposals for supporting optional type information
Backend Frameworks for Full-Stack GraphQL Type Safety* Juniper for Rust
* Hasura (database-schema based API)
* Postgraphile (database-schema based API)
* Discourse thread on differences between all the Elm graphql libraries
* harmboschloo/graphql-to-elm - library for generating Elm functions to make queries from GraphQL strings
Core mechanics of Elm modules
Giant update functions* You can think of the update function as a delegator - get things to the right place rather than doing the work itself
* elm-review
* TCC (test && commit || revert)
What are you gaining from extracting a module?* Protecting invariants * Hiding internals * Decoupling * TDD 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 it * Relentless, Tiny Habits * elm-test Elm Radio episode * Testing is helpful for identifying modules - see keystone testing habit blog post * Property based testing is a sign that something is a module - it has a clear property, which means you want to protect the internals * It's okay to get it wrong, just don't get it all wrong up front with premature abstractions.
The talks* Make Impossible States Impossible from Elm Conf 2016 * Make Data Structures from Elm Europe 2018 * Elm Radio Episode 2: Intro to Opaque Types
Dealing with Impossible States* Building 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 possible
More references* elm-css
* Tereza's line-charts package
* Tereza's elm Europe talk
* elm-graphql
* Gilded rose live stream
* Snapshot testing (also called Approval Tests)
* Jeremy Fairbank's Boolean Blindness talk
elm-spaelm-spa-example GitHub repoBrowser.applicationUrl.Parser - URL parsing in Elm for routing single-page appselm-shared-state pattern (formerly called elm-taco)Next.js and NuxtJSelm-spaGetting Started Resources* Offical elm-spa Guide
* #elm-spa-users channel on the official Elm slack
* elm-spa-realworld (Ryan's version of elm-spa-example using his elm-spa framework)
* Exploring elm-spa example - Richard's conference talk walking through codebase
* Richard's Frontend Masters courses focus heavily on his elm-spa-example repo
* Elm Radio Episode 7: Extending Elm
the difference between validation and parsing lies almost entirely in how information is preserved
Shotgun 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 failure
Maybe.withDefault might indicate an opportunity to parseTwo ways to use this technique:
elm-test Basics* elm-test NPM package
* elm-explorations/test Elm package
* elm-test init command
* Running elm-test finds exposed values of type Test
TDD Principles Testing in Elm is easier because it's just expectations of input to output (deterministic) * TDD is a design practice too * Programming by Intention * Writing test first makes code testable & decoupled * Red, green, refactor * YAGNI * "Make the change easy, then make the easy change" * Kent Beck's TDD by Example* * Here's a staring template of a code kata in Elm that you can use to practice * Emily Bache has many more code katas you can practice on her GitHub
Fuzz Testing* Also known as Property-Based Testing
* Martin Janiczek's elm-minithesis project
* elm-test's view testing API includes Test.Html.Query, Test.Html.Selector, and Test.Html.Event
View objects
* Testing pyramid
* Mocking and stubbing are not needed or possible in Elm
* Order dependent test helper in Ruby: i_suck_and_my_tests_are_order_dependent
When to Use Types or Tests* Jeroen's Safe Unsafe Operations blog post * Richard Feldman's talk on Types and Tests * Make Impossible States
Should you test implementation details?* Discourse thread discussing testing internals * Think in terms of a modules responsibility
Higher-Level Testing in Elmelm-program-test
Martin Janiczek's elm Europe talk on testing Msg's with ArchitectureTest
test-update packageelm-ui packageElement.padding (no concept of margin)Previously called style-elements* There used to be a notion of a single type defining all possible styles
* Latest 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/html
* elm-css package
* Mobster app
Escape hatches* Element.html works at leaf nodes, but elm-ui in general doesn’t mix with plain html
* Element.htmlAttribute
* Refactoring is a huge asset for a team, so much easier than css refactoring
* Doesn’t expose all the css tricks directly, sometimes you need escape hatches to access those
Responsiveness* Pass in window size from your Elm model
* Doesn’t use media queries, so that approach doesn't play well with with pre-rendered html like in elm-pages
* classifyDevice is an optional helper for responsiveness
Semantic html* Express layout with Element.row, column, el
* Semantic HTML is independent from layout. Set with attributes using the Element.Region module.
Wrapping* Element.paragraph uses text wrapping
em/rem* elm-ui doesn't expose access to rem and em units to simplify the mental model and reduce overlapping ways to express something
Cookbooks/examplesLucas Payr's elm-ui-widgets
Alex Korban's elm-ui patterns
)
Debugging elm-ui views* Element.explain gives you highlights around nested elements
* Inspecting developer tools doesn't help much with elm-ui, but elm-ui is much more traceable because it doesn't have layout cascading like CSS
Resources* Matt'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 talk
* Richard 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
What is a Builder?* Init a builder data structure with a set of reasonable defaults * Customize those defaults through a series of chained function calls * Builders have the same type for the return type and final argument, so that they work nicely in a pipeline
Resources and Examples* Luke Westby's http-builder package * Brian Hicks' Robot Buttons from Mars talk * elm-review package docs * elm-pages/phantom builder live coding * Richard Feldman's Oslo Elm Days keynote
What can you do with Elm?* Html * Http * Ports * Web Components
Different techniques for extending elm* elm-pages StaticHttp API
* Elm radio episode 1 on elm pages
* elm-graphql
* Codegen
* Macros
* Elixir exunit
* Wrapper elm apps
* Can emulate effect managers
* Platform.worker
* Introspection
* elm-typescript-interop
* Ports and flags
* Web Components
* Code transformation
* Elm asset loader webpack
* Hacking JS to get FFI
* Depending on internal details could end up with broken code
elm-hot and elm-hot-webpack-loader
Pitfalls and considerationsCodegen
Macros
Provide a platform with extensions in mind when you build tools so you don’t require users to hack
When you build a tool, think about the mental model for uses, let that guide you. Avoid leaky abstractions
Be opinionated about the core things, and unopionated about what’s not essential to the tool
[elm-spa](https://github.com/ryannhg/elm-spa)What is a parser?* yacc/lex
* AST (Abstract Syntax Tree) vs. CST (Concrete Syntax Tree)
* JSON decoding vs. parsing
* JSON decoding is validating a data structure that has already been parsed. Assumes a valid structure.
* elm/parser
* Haskell parsec library - initially used for the Elm compiler, now uses custom parser
What is a parser?* One character at a time * Takes input string, turns it into structued data (or error)
Comitting* Backtrackable parsers
* chompIf and chompWhile
* Parser.oneOf
Benchmarking* elm-explorations/benchmark
* Benchmark before making assumptions about where performance bottlenecks are
* Write unit tests for your parser
* GFM table parsing live stream
* Parser.succeed
Elm regex vs elm parserIndications that you might be better off with parser
Getting source code locations* Parser.getRow and getCol
* Parser.getSource
Parser.loop* Loop docs in elm/parser
* Looping allows you to track state and parse groups of expressions
* Loop over repeated expression type, tell it termination condition with Step type (Loop and Done)
Error Messages* You can fail with Parser.problem * Parser.Advanced module is designed to give you more precise context and error messages on failure * Parser.Advanced.inContext
Getting Started with a Parser Project* Write lots of unit tests with elm-test!
There's likely a specification doc if you're parsing a language or formal syntax
Look at examples of parser projects
dillonkearns/elm-markdownelm-in-elm parsermdgriffith/elm-markup - good reference for parsing, fault-tolerant parsing, and giving nice error messagesLook at elm/parser docs and resources
What is an Elm Package? Elm package repository
* Elm packages enforce SemVer for the public package API
* The SemVer (Semantic Versioning) Spec
* Interesting 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 package
* dict-extra package
* Minimize 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 package
Should you publish a package?* The Elm package ecosystem has a high signal to noise ratio * Elm packages always start at version 1.0.0 * SemVer has different semantics before 1.0.0 (patch releases can be breaking before 1) - see SemVer spec item 4
Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.
Keep yourself honest about solving meaningful problems* Start by asking "What problem are you solving? Who are you solving it for?"
* Scratch your own itch
* elm-graphql
* servant-elm (for Haskell servant)
* Keep yourself honest about solving problems by starting with an examples/ folder
* Early elm-graphql commits started with examples before anything else
* Write meaningful test cases with elm-test
* elm-verify-examples
* Have a clear vision
* Ask people for feedback
* Let ease of explanation guide you to refine core concepts
Make it easy for people to understand your package goals and philosophy Include code examples in readme and docs to make it easier for people to get started
* elm-review live stream video
* Use meaningful examples solving concrete problems (images/screenshots are good, too)
* Richard Feldman's Exploring elm-spa-example* talk
* Luke's elm-http-builder package
* elm-spa-example's custom http request builder module
* Instead of writing a package, in some cases it could make sense to publish a blog post to share a pattern
Porting libraries vs. Coming Up With an Idiomatic Solution for Elm* Instead of moment js ported to Elm, have an API built for a typed context
* Ryan's date-format package
How to design an Elm package API Define your constraints/guarantees, make impossible states impossible * Charlie Koster's Advanced Types in Elm* blog post series * Avoid exposing internals of your data * Elm Radio episode 002: Intro to Opaque Types
Pay attention to how other packages solve problems* Richard Feldman's talk The Design Evolution of elm-css and elm-test * Brian Hicks' talk Let's publish nice packages * Look at prior art, including in other ecosystems * Look at github issues and blog posts from projects in other ecosystems
Pick your constraints instead of trying to solve every problem* Helps you choose between tradeoffs * Having clear project goals explicitly in your Readme makes it easier to discuss tradeoffs with users and set expectations * Idiomatic elm package guide has lots of info on basic mechanics and best practices for publishing Elm packages
The mechanics of publishing an elm package* elm make --docs docs.json will tell you if you're missing docs or if there are documentation validation errors
* elm-doc-preview
* Can use elm-doc-preview site to share documentation of branches, or packages that haven't been published yet
* Set up a CI
* Dillon's CI script for dillonkearns/elm-markdown package
* Dillon'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 release
* elm 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 idea
Continue the ConversationShare your package ideas with us @elmradiopodcast on Twitter!
Basics* elm/json package docs
* Elm Guide section on JSON Decoders
* Validates 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 JSON* Bad 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 types * You can do data transformations locally as you build up your decoder, rather than passing your giant data structure through a single transform function
Decoding Into Ideal Types* Richard Feldman's elm-iso8601 package
* elm/time package
* Programming by intention
* Json.Decode.succeed is helpful for stubbing out data
* Dillon's Incremental Type Driven Design talk at elm Europe
* Json.Decode.fail lets you validate data and fail your whole decoder if there’s a problem
* Parse, don’t validate blog post by Alexis King
* Dillon's elm-cli-options-parser package
* Json.Decode.maybe docs
Note 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 resource* Brian Hicks' book The JSON Survival Kit
Joël Quenneville’s Blog Posts About JSON Decoders* Getting Unstuck with Elm JSON Decoders * 5 Common JSON Decoders * Elm's Universal Pattern
Guaranteeing that json is valid before runtime* elm-graphql package
* The basics of GraphQL
* Dillon's Types Without Borders Elm Conf talk
* Elm Radio 001 Getting Started with elm-pages
* elm-pages StaticHttp API docs
* Kris Jenkins' elm-export tool for Haskell types to Elm.
* Mario Rogic's Evergreen Elm elm Europe talk
Autogenerating json decoders* json-to-elm tool - generates Elm decoders from raw JSON values
* intellij-elm JSON decoder generator
Organizing your decoders* Evan Czaplicki's elm Europe keynote The life of a file * Evan's experience report on implicit decoding in Haskell
Getting Started* Understand Json.Decode.map
* Understand record type aliases - the function that comes from defining type alias Album = { ... }
Submit your question to Elm Radio!
Opaque TypesSome patterns
Package-Opaque ModulesExample - the Element type in elm-ui.
Definition of the Element type alias
elm-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
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/
Eleventy
Meta TagsOpen Graph tags
Asset 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 apps
Compared to extending the Gatsby webpack config
SOLID Open-Closed Principle
elm-pages showcase
Chandu's art showcase (built with elm-pages) - https://tennety.art/
Headless CMSes vs. monolothic site providershttps://www.sanity.io/
contentful.com
https://airtable.com/
netlifycms.org
CDN hosting provider Netlify
Static 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 flexible
More info on what exactly is the JAMstack?
Getting started with elm-pageselm-pages-starter repo
elm-pages vs. elm/browserPages.Platform.application
The 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 Concepts* SEO - elm-pages SEO API docs * Secrets - docs * Section in StaticHttp blog post about how you don't use Msgs for your StaticHttp data * generateFiles hook
Incremental Elm Live - Twitch streaming series
Where to learn more* elm-pages.com * Join the Elm slack and say hello in the elm-pages channel!