Skip to content

Best Practices for Iridium

These are recommendations for working with and organizing an Iridium-based application.

Want to contribute your recommendations?

Inspect your contexts

Frequently when using a callback like AfterStateUpdated or something as simple as LabelFn you want to use some additional information to set or control the behavior of the component. We make a concerted effort to document here what data and methods are available to you in your contexts, but sometimes we miss things.

We highly encourage you to inspect the contexts of your components to see what data and methods are available to you. Digging a little beyond Iridium's surface yourself can help you understand how to create your application in a more efficient way.

Use .templ files

If you choose to create your own custom components for Iridium, we highly recommend creating dedicated .templ files for organization.

You are able to inline your custom components using templ, but this is bad for maintainability and readability.

Escape user content in templ files

A very common oversight when developping your own custom .templ files with Alpine.js is misunderstanding what HTML content is escaped by templ and what is not.

Templ's HTML escaping does not protect you when manually creating JS strings and injecting them for use with Alpine.

go
// BAD!
templ BadComponent(userValue string) {
    <div x-data={"{ value: '" + userValue + "' }"}></div>
}

That userValue is not escaped, so if you source its value from your users, and they provide the string : ' + alert(document.cookie) + ' you just got yourself pwned.

go
// SAFE - user input passed through json.Marshal
templ GoodComponent(userValue string) {
    {{
        valueJSON, _ := json.Marshal(userValue)
        value := string(valueJSON)

        // Or using templ's method
        value, _ = templ.JSONString(userValue)
    }}
    <div x-data={ fmt.Sprintf("{ value: %s }", value) }></div>
}

Always json encode your user values if they will be evaluated by Alpine! See more here

Project structure

It's recommened to group together your Iridium specific files into one general section in your application.

Here is an example of how to organize your Iridium project.

sh
# Root Project Dir
-- iridium/
    -- panels/
        -- admin_panel.go # Your adminstrator panel
        -- user_panel.go # Your user panel

    -- resources/
        -- users/ # A resource for your users
            -- user_resource.go # Create your resource + form + table
            -- pages/ # Define your custom pages
                -- user_list.go # Your user's list/table view
                -- user_create.go # Your user's create page
                -- user_edit.go # Your user's edit page
                -- user_view.go # Your user's view page
            -- widgets/ # Define user specific widgets
                -- user_count.go
        -- appointments/ # Another resource folder for appointments
            -- ...

    -- pages/ # General Pages
        -- external/ # Manage pages outside panels
            -- landing_page.go
        -- custom/ # Manage custom pages inside panels
            -- custom_page.go

    -- widgets/ # General widgets
        -- charts/ # Chart widgets
            -- appointment_by_location.go # Example Widget
        -- stats/ # Statistics widgets
            -- appointment_counts.go # Example Widget

    -- overrides/ # A place to house your overrides
        -- views/ # view overrides
            -- custom_view.go # A custom view override
        -- resolvers/ # resolver overrides
            -- custom_resolvers.go # A custom resolver override

    -- custom/ # A place to house some custom components
        -- fields/ # Form Fields
            -- custom_form_field.templ # A custom form field
        -- table/ # Table Columns
            -- custom_column.templ # A custom table field

Reading List

We're compiling a list of articles and blog posts that we think are relevant to Iridium and which we encourage users to read:

Released under the MIT License.