A beautiful, type-safe storage library for Elm applications. Simple, elegant, and powerful.
Just like the Ipê tree that blooms magnificently, this library aims to make your Elm applications flourish with elegant and reliable storage capabilities.
- Type-safe - Full Elm type safety for your storage operations
- Universal - Works with both LocalStorage and SessionStorage
- Simple API - Clean, intuitive interface
- Zero dependencies - Lightweight and focused
- Modern - Built for Elm 0.19.1+
- Reactive - Subscription-based data updates
- Error handling - Comprehensive error management
elm install heitorgandolfi/ipe-elm
port module Main exposing (..)
import Ipe exposing (StorageType(..), Error(..))
import Json.Encode as Encode
import Json.Decode as Decode
-- Required ports
port saveToStorage : Encode.Value -> Cmd msg
port loadFromStorage : Encode.Value -> Cmd msg
port removeFromStorage : Encode.Value -> Cmd msg
port receiveStorageResult : (Encode.Value -> msg) -> Sub msg
-- Helper functions to connect Ipê with your ports
saveToIpe : StorageType -> String -> Encode.Value -> Cmd msg
saveToIpe storageType key value =
Ipe.save storageType key value |> saveToStorage
loadFromIpe : StorageType -> String -> Cmd msg
loadFromIpe storageType key =
Ipe.load storageType key |> loadFromStorage
removeFromIpe : StorageType -> String -> Cmd msg
removeFromIpe storageType key =
Ipe.remove storageType key |> removeFromStorage
Copy this code to your JavaScript file and call setupIpePorts(app)
after initializing your Elm app:
function setupIpePorts(app) {
app.ports.saveToStorage.subscribe((payload) => {
try {
const { storageType, key, value } = payload;
const data = JSON.stringify(value);
if (storageType === "local") {
localStorage.setItem(key, data);
} else {
sessionStorage.setItem(key, data);
}
} catch (e) {
console.error("Ipê (save): Failed to save to storage.", e);
}
});
app.ports.loadFromStorage.subscribe((payload) => {
try {
const { storageType, key } = payload;
let data = null;
if (storageType === "local") {
data = localStorage.getItem(key);
} else {
data = sessionStorage.getItem(key);
}
let parsed = null;
if (data !== null) {
try {
parsed = JSON.parse(data);
} catch (parseError) {
parsed = data;
}
}
app.ports.receiveStorageResult.send({ key, data: parsed });
} catch (e) {
console.error("Ipê (load): Failed to load from storage.", e);
}
});
app.ports.removeFromStorage.subscribe((payload) => {
try {
const { storageType, key } = payload;
if (storageType === "local") {
localStorage.removeItem(key);
} else {
sessionStorage.removeItem(key);
}
} catch (e) {
console.error("Ipê (remove): Failed to remove from storage.", e);
}
});
}
// Initialize your Elm app and connect the ports
var app = Elm.Main.init({ node: document.getElementById('app') });
setupIpePorts(app);
type Msg
= SaveUser
| LoadUser
| StorageReceived Encode.Value
type alias User = { name : String, email : String }
-- Save data
saveUser : User -> Cmd Msg
saveUser user =
saveToIpe Local "current-user" (encodeUser user)
-- Load data
loadUser : Cmd Msg
loadUser =
loadFromIpe Local "current-user"
-- Remove data
removeUser : Cmd Msg
removeUser =
removeFromIpe Local "current-user"
-- Subscribe to storage events
subscriptions : Model -> Sub Msg
subscriptions _ =
receiveStorageResult StorageReceived
-- Handle storage responses
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
StorageReceived value ->
case Decode.decodeValue (Decode.field "key" Decode.string) value of
Ok "current-user" ->
handleUserData value model
_ ->
(model, Cmd.none)
-- ... other cases
-- Handle user data with Ipê's decoder
handleUserData : Encode.Value -> Model -> (Model, Cmd Msg)
handleUserData value model =
case Ipe.decodeStorageResult userDecoder value of
Ok user ->
({ model | user = Just user }, Cmd.none)
Err (Ipe.DecodeError error) ->
({ model | error = Just ("Decode error: " ++ Decode.errorToString error) }, Cmd.none)
Err Ipe.NotFound ->
({ model | user = Nothing }, Cmd.none)
type StorageType
= Local -- localStorage
| Session -- sessionStorage
type Error
= DecodeError Decode.Error -- JSON decoding failed
| NotFound -- Key not found in storage
Create a save command payload.
-- Create save payload
savePayload = Ipe.save Local "username" (Encode.string "john")
-- Use with your port
savePayload |> saveToStorage
Create a load command payload.
-- Create load payload
loadPayload = Ipe.load Local "username"
-- Use with your port
loadPayload |> loadFromStorage
Create a remove command payload.
-- Create remove payload
removePayload = Ipe.remove Local "username"
-- Use with your port
removePayload |> removeFromStorage
Decode storage results from JavaScript.
-- Handle storage response
case Ipe.decodeStorageResult userDecoder storageValue of
Ok user ->
-- Successfully decoded user
Err (DecodeError error) ->
-- Failed to decode
Err NotFound ->
-- Key not found in storage
Convert storage type to string (for advanced usage).
Ipe.storageTypeToString Local -- "local"
Ipe.storageTypeToString Session -- "session"
Check out the /example
directory for a complete, beautiful example application that demonstrates:
- Saving and loading user profiles
- Session theme management
- Error handling scenarios
- Modern, responsive UI
- Real-world usage patterns
cd example
elm make Main.elm --output=main.js
# Open index.html in your browser
The JavaScript bridge is essential for Ipê to work. It handles the actual browser storage operations and communicates with your Elm application through ports.
- Automatic JSON handling - Serializes/deserializes data automatically
- Error resilience - Graceful error handling and logging
- Storage abstraction - Works with both localStorage and sessionStorage
- Type preservation - Maintains data types when possible
- Copy the
setupIpePorts
function to your project - Call it after initializing your Elm app
- That's it! Ipê handles the rest
ipe-elm/
├── src/
│ └── Ipe.elm # Main library module
├── example/
│ ├── Main.elm # Example application
│ ├── index.html # Example HTML with styling
│ └── main.js # Compiled example (generated)
├── js/
│ └── storage.js # JavaScript bridge
├── elm.json # Package configuration
└── README.md # This file
Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests.
git clone https://github.com/heitorgandolfi/ipe-elm.git
cd ipe-elm
elm make src/Ipe.elm
- Elm 0.19.1+
- Browser with localStorage/sessionStorage support
- JavaScript enabled
- ✨ Core storage operations (save, load, remove)
- ✨ Support for localStorage and sessionStorage
- ✨ Type-safe error handling
- ✨ Subscription-based updates
- ✨ Complete example application
- ✨ Modern, beautiful UI example
BSD 3-Clause - see LICENSE for details.
- Built with ❤️ for the Elm community
- Inspired by the beauty of Brazilian Ipê trees
- Special thanks to all contributors and users
Made with 🌸 by the Elm community Bringing the beauty of Ipê flowers to your Elm applications