13
6
Fork
You've already forked ichor
9
elixir-based conjured.ink droplet
  • Elixir 87.5%
  • CSS 4.9%
  • HTML 3.8%
  • TypeScript 2.9%
  • JavaScript 0.9%
Hannah Read ab652f3170
Some checks failed
CI / Test on OTP 26.0.1 / Elixir 1.16.1 / Node 20.11.1 (push) Failing after 1m53s
comment elixir setup out temporarily
2025年08月02日 16:19:37 -04:00
.github/workflows comment elixir setup out temporarily 2025年08月02日 16:19:37 -04:00
.vscode Add Phoenix extension 2025年07月28日 03:46:41 +02:00
assets rename to ichor 2025年07月24日 22:50:21 -07:00
config Add Oban 2025年07月27日 22:35:31 -07:00
lib Add Oban 2025年07月27日 22:35:31 -07:00
priv Add Oban 2025年07月27日 22:35:31 -07:00
test pull in forex stuff from Banchan 2025年07月28日 02:09:46 +02:00
workflows add test worflow 2025年08月02日 14:11:04 -04:00
.editorconfig initial commit 2025年07月15日 02:29:40 -07:00
.formatter.exs initial commit 2025年07月15日 02:29:40 -07:00
.gitignore pull in forex stuff from Banchan 2025年07月28日 02:09:46 +02:00
.tool-versions initial commit 2025年07月15日 02:29:40 -07:00
docker-compose.yaml initial commit 2025年07月15日 02:29:40 -07:00
LICENSE.md add license 2025年07月26日 23:25:33 -07:00
mix.exs Add Oban 2025年07月27日 22:35:31 -07:00
mix.lock Add Oban 2025年07月27日 22:35:31 -07:00
README.md Replace content with media 2025年07月28日 19:13:56 -06:00

ichor

Table of Contents

Welcome

Ichor is a droplet (a self-hosted website by individual creatives) meant to be used with Conjured Ink. For more information on the philosophy and goals here, check out the README over there.

Ichor itself is meant to be easy to use and set up for even non-technical people. The process should look something like:

  1. Get a host for your server, perhaps pick one out from our wiki
  2. Deploy Ichor to the host (this is in-development software, instructions for this coming soon!)
  3. Use a payment processor plugin if you're planning on selling your media. We have a list of potentially interesting payment processors on our wiki.
  4. Apply for your site to be listed in a Conjured Ink index. Pick one appropriate for you and the media you create!

Ichor is not the only way to interface with Conjured Ink indexes; any sort of website can. This means that you could extend Ichor if it's missing features that you need for your specific use case (and possibly open a PR to add it, PRs are always welcome). Or, you could roll your own host, you could even make a collective for similar artists which then gets indexed by a Conjured Ink indexer.

Ichor also doesn't have to be used with Conjured Ink, though that is the intent. One could use it for their indie site without having anything to do with an indexer.

Features

  • User accounts, with authentication, login/signup, and email verification
  • User settings page scaffold
  • Primarily server-side rendered, with web components set up for if/when needed
  • Web components are ALSO SSR'd as needed
  • No Tailwind/React/etc. Just plain ol' HTML/CSS, a sprinkling of JS, and good vibes.
  • TypeScript support
  • Full setup for bundling and minifying JS and CSS from sources
  • Ready-to-use i18n and locale detection/configuration
  • Transactional email sending (needs a service for live site)
  • Rate limiting
  • Websockets available if needed (not connected by default)
  • Autoformatting for both JSTS and Elixir code
  • CSS-based light/dark/etc theming support with built-in picker
  • Scaffolded CSP
  • Ready-to-go DNS-based clustering for horizontal scaling (you don't need it)
  • Root template with a bunch of nice things:
    • Mobile size-related meta tags
    • Anti-AI no-scan stuff (on top of included robots.txt). For all the good it'll do :/
    • OpenGraph/"Twitter" card properties, configurable per-page.

Setting up

Prerequisites

Tip

See Using ASDF for Runtimes for a convenient way to handle the first two items below.

  • Elixir and Erlang (Typically auto-installs with Elixir)
  • NodeJS
  • inotify-tools (Linux only) - Install through your preferred package manager

Note

You can check .tool-versions in this repository to see what this project is typically developed against.

Using ASDF for runtimes

You can use ASDF to install Elixir, Erlang, and NodejS at the correct versions (ensure the necessary build deps are installed first):

asdf plugin add nodejs
asdf plugin add erlang
asdf plugin add elixir
KERL_BUILD_DOCS=yes asdf install # will install erlang (w/ docs), elixir, and nodejs

Additional Tooling

If you're using VS Code, you may find these extensions useful:

Up and Running

Just a couple more commands and we're all set:

  • mix local.hex to install hex package manager
  • mix archive.install hex phx_new
  • cp config/dev.secret.example.exs config/dev.secret.exs
  • cp config/test.secret.example.exs config/test.secret.exs copy example secret files
  • mix setup to install deps, create the database, install JS deps, and build JS assets
  • mix phx.server to run the server

Now you can visit localhost:4000 from your browser.

Architecture

Stack

Backend

Frontend

  • Plain old HTML + CSS (only preprocessing for CSS is bundling/minification)
  • Lit for dynamic components
  • TypeScript

JS Considerations and SSR

We use TypeScript for all client-side code, and Lit for all client-side components. Components should be small and focused, preferring to use server-side Phoenix Components whenever possible.

When JavaScript SSR is enabled, we do some additional steps.

We generate as much html/css as possible server-side, and try to keep our JS payloads as small as possible. Server-side rendering, or SSR, is done in three layers:

  1. Phoenix controllers render a dynamic page with as much of the content in regular light DOM as possible. This content can be styled with our global CSS styles, and does not require JS to render/function.
    • This uses Phoenix HEEx templates and Components.
    • Within these templates, we can insert Lit components for things that will absolutely need dynamic, client-side/JS behavior or will otherwise have to do something special to function while offline.
  2. Once Phoenix renders these templates, they're passed through the Plug system, which eventually invokes a Lit server-side renderer.
    • This renderer takes the template, loads all existing components, and pre-renders Lit components as far as server-side work will allow.
    • In components, this behavior can be controlled with isServer.
  3. Finally, all this server-side-rendered content is sent to the client, and Lit components will be "hydrated" after all the other content and JS is loaded.

As a general rule, we operate on "the less JavaScript, the better". Dependencies should be few and far between, preferring to use built-in browser features whenever possible. If a dependency is needed, it should be small and focused, and not introduce a lot of overhead. Obviously, some things in offline apps are just going to bring in some bulk and that's ok, but whenever we have a choice between two things, code size should be a significant consideration in their evaluation.

To minimize JavasScript, we should err on the side of having components be Phoenix-based, and only use Lit components when absolutely necessary: even if they're server-side rendered, their JavaScript definitions still needs to load/hydrate, and are still shipped as part of our .js bundles.

To see what kind of weight a dependency brings in, you can use BundlePhobia.

Folder Structure

  • assets/ - Frontend code
    • css/ - CSS files
      • components/ - CSS for (usually server-side) components
      • app.css - main css entrypoint
      • theme-*.css - variables for themes
      • variables.css - non-theme-specific variables
        • NOTE: While regular styles don't leak into shadow DOM, --variables do, so we can use this for things we need to have consistent styling for.
    • js/ - JS/TS files
      • components/ - Toplevel lit components
      • app.ts - entry point for the overall site JS
      • lit-ssr.ts - lit server-side renderer tool. Used as a server-side script. Kept here for convenience.
      • Other files are pulled in by one of these.
  • config/ - Configuration files
    • Different configs for dev, prod, and test envs.
    • config.exs - common config
    • runtime.exs - more prod config
  • lib/ - Elixir source code
    • ichor/ - core business logic. No web stuff here. All modules are prefixed with Ichor.
    • ichor_web/ - all web stuff here. Modules are prefixed with IchorWeb. Uses Ichor for any business logic.
  • priv/ - miscellaneous things
    • gettext/ - this is where our (server-side) i18n stuff lives
    • repo/ - migrations, seeds, etc
    • static/ - static files. JS and CSS are compiled into here (but .gitignored)