github.com/dracory/cmsstore
cmsstore is a CMS-focused store that manages sites, pages, templates, blocks, menus, translations, and shortcodes. It gives Go applications a ready-made content layer backed by SQL with interface-driven design.
Highlights
- Multisite aware – manage multiple sites from a single store instance with per-site templates, pages, blocks, menus, and translations.
- Shortcodes – register custom shortcode renderers to inject dynamic content into pages.
- Rich page model – pages support custom templates, SEO metadata, middleware hooks, and soft deletion.
- Reusable blocks & menus – blocks provide reusable content snippets; menus define navigations with metadata and ordering helpers.
- Translations – key/value translation entries scoped to site and locale for multi-language content.
- Schema via migrations – schema creation is handled by migration files, not automigration.
Creating a Store
func NewCmsStore(db *sql.DB, debug bool) (cmsstore.StoreInterface, error) {
st, err := cmsstore.NewStore(cmsstore.NewStoreOptions{
DB: db,
BlockTableName: "snv_cms_block",
PageTableName: "snv_cms_page",
TemplateTableName: "snv_cms_template",
SiteTableName: "snv_cms_site",
MenusEnabled: true,
MenuItemTableName: "snv_cms_menu_item",
MenuTableName: "snv_cms_menu",
TranslationsEnabled: true,
TranslationTableName: "snv_cms_translation",
VersioningEnabled: true,
VersioningTableName: "snv_cms_version",
})
if err != nil {
return nil, err
}
st.EnableDebug(debug)
return st, nil
}
-
Menus support – enabled with
MenusEnabled: true,MenuTableName, andMenuItemTableName. -
Versioning support – enabled with
VersioningEnabled: trueandVersioningTableName. -
Translations support – enabled with
TranslationsEnabled: trueandTranslationTableName. - Debug is controlled via
st.EnableDebug(debug)after store creation. -
Schema creation is handled by migration files in
database/migrations/(invoked viamigrations.MigrateAll(app)), not by automigration. -
Register shortcode implementations via
ShortcodeInterfacefor dynamic rendering.
Working with Pages
page := cmsstore.NewPage().
SetSiteID(siteID).
SetSlug("about").
SetTitle("About Us").
SetTemplateID(templateID).
SetContent("<p>Hello world</p>").
SetStatus(cmsstore.PAGE_STATUS_PUBLISHED)
if err := store.PageCreate(ctx, page); err != nil {
log.Fatal(err)
}
page.SetSEODescription("Learn more about our company")
if err := store.PageUpdate(ctx, page); err != nil {
log.Fatal(err)
}
-
Pages expose helpers for SEO fields, visibility scheduling, middleware, and
metadata via
SetMetas. -
Use
PageListwithPageQuery()to filter by site, status, slug, template, created range, etc.
Blocks, Menus, Templates, Translations
block := cmsstore.NewBlock().
SetSiteID(siteID).
SetSlug("footer").
SetContent("<footer>...</footer>")
if err := store.BlockCreate(ctx, block); err != nil {
log.Fatal(err)
}
menu := cmsstore.NewMenu().
SetSiteID(siteID).
SetSlug("main-nav").
SetItemsJSON(`[{"title":"Home","url":"/"}]`)
_ = store.MenuCreate(ctx, menu)
- Templates capture layouts (HTML/Go template markup) with metadata and soft-delete support.
-
Translations store key/value pairs per locale and can be queried via
TranslationQuery()to build localized content.
Shortcodes
- Implement
cmsstore.ShortcodeInterface(alias, description, render). - Register the shortcode in
NewStoreOptions.Shortcodes. - Use the shortcode delimiters in page content; cmsstore renders during processing.
Shortcodes live in your Go codebase, so they are version-controlled and share application dependencies.
Related Topics
- Design Principles – review the shared store architecture.
- Entities & Interfaces – explore how cmsstore embeds the dataobject traits.
- Testing – repository uses SQLite-based tests to validate functionality.
- Create Your Own Store – extend cmsstore patterns for custom CMS features or integrations.