Haskell codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.
This codebase was created to demonstrate a fully fledged fullstack application built with Haskell/Scotty including CRUD operations, authentication, routing, pagination, and more.
We've gone to great lengths to adhere to the Haskell/Scotty community styleguides & best practices.
For more information on how to this works with other frontends/backends, head over to the RealWorld repo.
Since this is small application (only ~2k actual LOC), I've opted for a very vertical-slice-esque architecture, with each endpoint getting its own file, and with common logic simply going in its own files. Controllers, services, and data access are of course still decoupled through MTL style classes (inspired by three-layer-cake), making testing extremely simple. I believe the general architecture should be quite self explanitory and easy to refactor as the app scales. I will admit it is slightly influenced by Haskell's dissallowance of circular imports, esp. as I didn't want to deal with hs-boot files.
Feel free to let me know your thoughts, or open an issue!
View more fine-grained documentation here.
app/ # The entrypoint into the application.
Main.hs # Very thin, just deals with configuration.
sqlbits/ # Some sql files w/ triggers/functions
# which are embedded directly within
# the haskell files via TemplateHaskell.
src/ # The actual source code for Conduit.
Conduit/App/ # This folder deals with the App Monad,
# which holds the server's global state.
Conduit/DB/ # Holds some DB-related utilities and
# code for decoupling/abstraction purposes.
# Also holds some DB initializtion code.
Conduit/Features/ # Contains the bulk of the Conduit logic,
# including the API endpoints/services/DB
# access logic.
# Also holds feature-related DB/error logic.
Conduit/Identity/ # Holds the code for the JWT-based auth.
# uses argon2 for pw hashing.
Validation.hs # Some utilities for basic validation
# of incoming data.
static/ # Holds the static files where the avatar
# images reside. The images are actually just
# blank files for now but it's fiiine.
test/ # Contains the unit tests made w/ hspec,
# currently only have tests for auth and
# slug-building since cypress covers the rest.
package.yaml # Describes the project and its dependencies.
realworld-hs.cabal # hpack generates the .cabal file from the
# package.yaml which, IMO, is much nicer
# to work with.
conduit-schema.json # The configuration files for conduit itself.
conduit.json # The schema file for your convenience.
(Not including common dependencies such as mtl
and aeson
)
scotty
— The minimal web "framework" which makes this all possiblerelude
— A nicer/safe Prelude alternativeesqueleto
— A type-safe SQL eDSL wrappingpersistent
jwt
— Library for working w/ JWTscryptonite
— Low-level cryptography librarywai-middleware-static
— Used to easily serve static files
This project requires Cabal & a running Postgres instance. Here're a couple links of that may help you out:
- Cabal via GHCup — Guide for installing + getting started w/ Cabal
- Postgres + Docker — A quick tutorial for getting a Postgres container running
To begin, of course, clone the repo and cd into it:
git clone https://github.com/toptobes/realworld-scotty-hs.git && cd realworld-scotty-hs
# or
gh repo clone toptobes/realworld-scotty-hs && cd realworld-scotty-hs
From there, update the appropriate configs in conduit.json
- It's already set with sensible defaults; be sure to double-check the postgres connection string
- there is a
conduit-schema.json
for your convenience as well that provides extra info - If necessary, you can set the
CONDUIT_CONFIG
env var to to some custom config path
Then, you can start the app via cabal run app
, or run the unit tests w/ cabal run spec
.
It may take a while the first time while it obtains/builds the relevant dependencies.
If you plan to make any modifications involving creating new files or adding new dependencies, you may need hpack.
- You could update the
realworld-hs.cabal
file manually if you really wanted or needed to though - Otherwise, just run the
hpack
command whenever you modifypackage.yaml
You can create the documentation site for this project using cabal haddock
, and then access it w/ npx serve
or whatever
else you fancy. Nearly everything except for the features are decently documented, and I'll work on adding more soon.
Or just read through the code manually if you prefer, whatever you want lol.