Fabrica Blog

Simple guides introducing Fabrica with hands-on examples.

View the Project on GitHub OpenCHAMI/fabrica

Getting Started with Fabrica

This guide will walk you through creating your first REST API with Fabrica in about 15 minutes.

Prerequisites

Installation

Install the Fabrica CLI:

go install github.com/openchami/fabrica/cmd/fabrica@latest

Verify installation:

fabrica --version
# Output: fabrica version v0.4.0

Create Your First API

Step 1: Initialize Project

fabrica init bookstore
cd bookstore

This creates:

bookstore/
├── .fabrica.yaml        # Project configuration
├── apis.yaml            # API groups/versions/resources
├── apis/                # Versioned API definitions
│   └── example.fabrica.dev/
│       └── v1/          # Hub version (default)
├── cmd/
│   └── server/          # API server (main.go with stubs)
├── internal/            # Generated code will go here
├── go.mod
├── go.sum
└── README.md

Step 2: Add Your First Resource

fabrica add resource Book

This creates apis/example.fabrica.dev/v1/book_types.go:

package v1

import (
  "context"

  "github.com/openchami/fabrica/pkg/fabrica"
)

// Book represents a Book resource
type Book struct {
  APIVersion string           `json:"apiVersion"`
  Kind       string           `json:"kind"`
  Metadata   fabrica.Metadata `json:"metadata"`
  Spec       BookSpec   `json:"spec"`
  Status     BookStatus `json:"status"`
}

// BookSpec defines the desired state of Book
type BookSpec struct {
    Title       string `json:"title" validate:"required,min=1,max=100"`
    Author      string `json:"author" validate:"required,min=1,max=50"`
    Description string `json:"description,omitempty" validate:"max=500"`
    Price       float64 `json:"price" validate:"min=0"`
    InStock     bool   `json:"inStock"`
}

// BookStatus defines the observed state of Book
type BookStatus struct {
    Phase       string `json:"phase,omitempty"`
    Message     string `json:"message,omitempty"`
    Ready       bool   `json:"ready"`
    LastUpdated string `json:"lastUpdated,omitempty"`
}

func (r *Book) Validate(ctx context.Context) error { // Add custom validation logic here return nil }


### Step 3: Customize Your Resource

Edit `apis/example.fabrica.dev/v1/book_types.go` and modify the `BookSpec` fields as needed:

```go
type BookSpec struct {
    Title       string `json:"title" validate:"required,min=1,max=200"`
    Author      string `json:"author" validate:"required,min=1,max=100"`
    Description string `json:"description,omitempty" validate:"max=500"`
    Price       float64 `json:"price" validate:"min=0"`
    InStock     bool   `json:"inStock"`
}

type BookStatus struct {
    Phase       string `json:"phase,omitempty"`
    Message     string `json:"message,omitempty"`
    Ready       bool   `json:"ready"`
    LastUpdated string `json:"lastUpdated,omitempty"`
}

Step 4: Generate Code

fabrica generate

Output:

🔧 Generating code...
📦 Found 1 resource(s): Book
  ├─ Registering Book...
  ├─ Generating handlers...
  ├─ Generating storage...
  ├─ Generating OpenAPI spec...
  ├─ Generating client code...
  └─ Done!

✅ Code generation complete!

This generates:

Step 5: Update Dependencies

After code generation, update your Go module dependencies:

go mod tidy

This resolves all the new imports that were added by the code generator.

Step 6: Run Your API

go run ./cmd/server/

Your API is now running at http://localhost:8080!

Using Your API

Create a Book

curl -X POST http://localhost:8080/books \
  -H "Content-Type: application/json" \
  -d '{
    "name": "golang-guide",
    "title": "The Go Programming Language",
    "author": "Alan Donovan",
    "description": "A comprehensive guide to Go programming",
    "price": 44.99,
    "inStock": true
  }'

Response:

{
  "apiVersion": "v1",
  "kind": "Book",
  "metadata": {
    "name": "golang-guide",
    "uid": "boo-abc123def456",
    "createdAt": "2025-10-15T10:00:00Z",
    "updatedAt": "2025-10-15T10:00:00Z"
  },
  "spec": {
    "title": "The Go Programming Language",
    "author": "Alan Donovan",
    "description": "A comprehensive guide to Go programming",
    "price": 44.99,
    "inStock": true
  },
  "status": {
    "phase": "Active",
    "ready": true,
    "lastUpdated": "2025-10-15T10:00:00Z"
  }
}

List Books

curl http://localhost:8080/books

Get a Specific Book

curl http://localhost:8080/books/boo-abc123def456

Update a Book

curl -X PUT http://localhost:8080/books/boo-abc123def456 \
  -H "Content-Type: application/json" \
  -d '{
    "name": "golang-guide",
    "title": "The Go Programming Language",
    "author": "Alan Donovan",
    "description": "Updated comprehensive guide to Go programming",
    "price": 39.99,
    "inStock": false
  }'

Delete a Book

curl -X DELETE http://localhost:8080/books/boo-abc123def456

Understanding the Resource Model

Fabrica uses a Kubernetes-style resource model with a flattened envelope pattern:

type Book struct {
    APIVersion string       `json:"apiVersion"`
    Kind       string       `json:"kind"`
    Metadata   Metadata     `json:"metadata"`
    Spec       BookSpec     `json:"spec"`
    Status     BookStatus   `json:"status,omitempty"`
}

Key concepts:

Validation

Fabrica uses struct tag validation for request validation:

type BookSpec struct {
    Title  string  `json:"title" validate:"required,min=1,max=200"`
    Price  float64 `json:"price" validate:"min=0"`
    Author string  `json:"author" validate:"required,min=1,max=100"`
}

Common validators:

Storage Options

File-Based Storage (Default)

Perfect for development:

backend, err := storage.NewFileBackend("./data")

Data stored in ./data/ directory as JSON files.

Database Storage (Production)

Use Ent for production:

fabrica init myapp --storage=ent --db=postgres

See Storage Guide for details.

Next Steps

Now that you have a working API:

  1. Add More Resources - fabrica add resource Author
  2. Add Custom Middleware - Implement authentication/authorization in internal/middleware/
  3. Add Validation - See Validation Guide
  4. Use the Client - Generated Go client in pkg/client/
  5. Add Events - See Events Guide
  6. Deploy - Build with go build cmd/server/main.go

Common Tasks

Add Another Resource

fabrica add resource Author
# Edit apis/example.fabrica.dev/v1/author_types.go
fabrica generate

Regenerate After Changes

# After editing resource definitions
fabrica generate

Build for Production

go build -o bookstore-api cmd/server/main.go
./bookstore-api

Run Tests

go test ./...

Troubleshooting

Error: “go: updates to go.mod needed”

Fix: Run go mod tidy after fabrica generate to resolve all new imports created by the code generator.

Error: “no resources found”

Fix: Make sure your resource has the flattened envelope structure:

type MyResource struct {
    APIVersion string       `json:"apiVersion"`
    Kind       string       `json:"kind"`
    Metadata   Metadata     `json:"metadata"`
    Spec       MyResourceSpec `json:"spec"`
}

Error: “failed to read embedded template”

Fix: Update fabrica: go install github.com/openchami/fabrica/cmd/fabrica@latest

Further Reading

Get Help