Skip to content

dporkka/go-htmx-supabase-saas

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Enterprise SaaS Platform

A professional, enterprise-grade SaaS application built with Go (Gin), Supabase, HTMX, and Alpine.js. Features a powerful plugin architecture for easy extensibility.

image

πŸš€ Features

  • πŸ” Secure Authentication - Built-in authentication with Supabase Auth, supporting OAuth, SSO, and MFA
  • πŸ”Œ Plugin Architecture - Extensible plugin system for easy customization and feature additions
  • ⚑ Lightning Fast - Built with Go and HTMX for optimal performance with minimal JavaScript
  • πŸ—„οΈ Supabase Integration - Seamless database and real-time subscriptions
  • 🎨 Modern UI - Beautiful, responsive UI with Tailwind CSS and Alpine.js
  • πŸ“± Responsive Design - Mobile-first design that works on all devices
  • πŸŒ™ Dark Mode - Built-in dark mode support
  • πŸ”’ Security First - CSRF protection, rate limiting, security headers

πŸ› οΈ Tech Stack

  • Backend: Go, Gin Framework
  • Database & Auth: Supabase (PostgreSQL + Auth)
  • Frontend: HTMX, Alpine.js, Tailwind CSS
  • Icons: Lucide Icons
  • Charts: Chart.js

πŸ“ Project Structure

saas-platform/
β”œβ”€β”€ cmd/api/              # Application entry point
β”œβ”€β”€ internal/
β”‚   β”œβ”€β”€ config/          # Configuration management
β”‚   β”œβ”€β”€ handlers/        # HTTP request handlers
β”‚   β”œβ”€β”€ middleware/      # Gin middleware
β”‚   β”œβ”€β”€ plugins/         # Plugin system core
β”‚   └── supabase/        # Supabase client
β”œβ”€β”€ pkg/
β”‚   └── logger/          # Structured logging
β”œβ”€β”€ plugins/             # Plugin implementations
β”‚   β”œβ”€β”€ dashboard/       # Dashboard plugin
β”‚   β”œβ”€β”€ users/           # User management plugin
β”‚   └── settings/        # Settings plugin
β”œβ”€β”€ web/
β”‚   β”œβ”€β”€ static/          # Static assets
β”‚   └── templates/       # HTML templates
β”œβ”€β”€ migrations/          # Database migrations
└── scripts/             # Utility scripts

πŸš€ Getting Started

Prerequisites

  • Go 1.21 or higher
  • Supabase account
  • Node.js (for Tailwind CSS, optional)

Installation

  1. Clone the repository:
git clone https://github.com/your-org/saas-platform.git
cd saas-platform
  1. Copy the environment file:
cp .env.example .env
  1. Update the .env file with your Supabase credentials:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-supabase-anon-key
SUPABASE_JWT_SECRET=your-supabase-jwt-secret
  1. Install dependencies:
go mod download
  1. Run the application:
go run cmd/api/main.go

The application will be available at http://localhost:8080.

πŸ”Œ Plugin System

The platform includes a powerful plugin architecture that allows you to easily extend functionality.

Creating a Plugin

  1. Create a new directory in plugins/:
mkdir plugins/myplugin
  1. Create a myplugin.go file:
package myplugin

import (
    "context"
    "net/http"
    
    "github.com/enterprise/saas-platform/internal/config"
    "github.com/enterprise/saas-platform/internal/plugins"
    "github.com/enterprise/saas-platform/internal/supabase"
    "github.com/enterprise/saas-platform/pkg/logger"
    "github.com/gin-gonic/gin"
)

type Plugin struct {
    *plugins.BasePlugin
    client *supabase.Client
    logger *logger.Logger
}

func NewMyPlugin() plugins.Plugin {
    return &Plugin{
        BasePlugin: plugins.NewBasePlugin(
            "myplugin",
            "1.0.0",
            "My custom plugin",
            "Your Name",
        ),
    }
}

func (p *Plugin) Initialize(ctx context.Context, cfg *config.Config, client *supabase.Client, logger *logger.Logger) error {
    p.client = client
    p.logger = logger
    return nil
}

func (p *Plugin) Shutdown(ctx context.Context) error {
    return nil
}

func (p *Plugin) RegisterRoutes(router *gin.RouterGroup, authMiddleware gin.HandlerFunc) {
    router.GET("/hello", authMiddleware, func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"message": "Hello from my plugin!"})
    })
}

func (p *Plugin) GetMenuItems() []plugins.MenuItem {
    return []plugins.MenuItem{
        {
            ID:       "myplugin",
            Label:    "My Plugin",
            Icon:     "star",
            Route:    "/plugins/myplugin",
            Position: 50,
        },
    }
}

func (p *Plugin) GetPermissions() []plugins.Permission {
    return []plugins.Permission{
        {
            ID:          "myplugin.view",
            Name:        "View My Plugin",
            Description: "Access my plugin",
            Category:    "My Plugin",
        },
    }
}
  1. Register your plugin in cmd/api/main.go:
import "github.com/enterprise/saas-platform/plugins/myplugin"

// In main():
pluginRegistry.Register(myplugin.NewMyPlugin())

Plugin Interface

All plugins must implement the following interface:

type Plugin interface {
    // Metadata
    Name() string
    Version() string
    Description() string
    Author() string

    // Lifecycle
    Initialize(ctx context.Context, config *config.Config, client *supabase.Client, logger *logger.Logger) error
    Shutdown(ctx context.Context) error

    // Routes
    RegisterRoutes(router *gin.RouterGroup, authMiddleware gin.HandlerFunc)

    // Hooks
    GetHooks() []Hook

    // Menu items
    GetMenuItems() []MenuItem

    // Permissions
    GetPermissions() []Permission

    // Enabled
    IsEnabled() bool
    Enable()
    Disable()
}

Plugin Hooks

Plugins can register hooks to respond to system events:

func (p *Plugin) GetHooks() []plugins.Hook {
    return []plugins.Hook{
        {
            Name:     "user.created",
            Priority: 10,
            Handler: func(data interface{}) error {
                // Handle user creation
                return nil
            },
        },
    }
}

Available hooks:

  • user.created - Fired when a new user is created
  • user.updated - Fired when a user is updated
  • user.login - Fired when a user logs in
  • settings.updated - Fired when settings are updated

πŸ” Authentication

The platform uses Supabase Auth for authentication. Supported methods:

  • Email/Password
  • OAuth (GitHub, Google, etc.)
  • Magic Links
  • SSO (Enterprise plans)

Protecting Routes

// In your plugin
func (p *Plugin) RegisterRoutes(router *gin.RouterGroup, authMiddleware gin.HandlerFunc) {
    // Public route
    router.GET("/public", publicHandler)
    
    // Protected route
    router.GET("/private", authMiddleware, privateHandler)
    
    // Role-based protection
    router.GET("/admin", authMiddleware, middleware.RequireRole("admin"), adminHandler)
}

🎨 Frontend

The frontend uses HTMX for dynamic interactions and Alpine.js for reactivity.

HTMX Examples

<!-- Load content dynamically -->
<div hx-get="/api/data" hx-trigger="load">
    Loading...
</div>

<!-- Form submission -->
<form hx-post="/api/submit" hx-swap="outerHTML">
    <input type="text" name="data">
    <button type="submit">Submit</button>
</form>

<!-- Infinite scroll -->
<div hx-get="/api/more" hx-trigger="revealed">
    Load more...
</div>

Alpine.js Examples

<div x-data="{ open: false }">
    <button @click="open = !open">Toggle</button>
    <div x-show="open">Content</div>
</div>

πŸ—„οΈ Database

The platform uses Supabase (PostgreSQL) for data storage.

Using the Supabase Client

// Select data
users, err := client.Select(ctx, "users", []string{"id", "email", "name"}, map[string]interface{}{
    "status": "active",
})

// Insert data
user, err := client.Insert(ctx, "users", map[string]interface{}{
    "email": "user@example.com",
    "name":  "John Doe",
})

// Update data
updated, err := client.Update(ctx, "users", "user-id", map[string]interface{}{
    "name": "Jane Doe",
})

// Delete data
err := client.Delete(ctx, "users", "user-id")

πŸ“ Logging

The platform includes a structured logger with multiple levels:

logger.Debug("Debug message")
logger.Info("Info message")
logger.Warn("Warning message")
logger.Error("Error message")
logger.Fatal("Fatal message") // Exits the application

πŸ§ͺ Testing

Run tests:

go test ./...

Run tests with coverage:

go test -cover ./...

πŸš€ Deployment

Docker

FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o main cmd/api/main.go

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
COPY --from=builder /app/web ./web
CMD ["./main"]

Environment Variables

Make sure to set all required environment variables in production:

  • SUPABASE_URL
  • SUPABASE_KEY
  • SUPABASE_JWT_SECRET
  • SESSION_SECRET (change from default!)

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

🀝 Contributing

Contributions are welcome! Please read our Contributing Guide for details.

πŸ“ž Support

For support, email support@example.com or join our Slack channel.

πŸ™ Acknowledgments

Releases

No releases published

Sponsor this project

Packages

 
 
 

Contributors