onmetal-dev metal .cursorrules file for Go (stars: 4)

- Don't capitalize the first letter of a comment
- The first letter of Go error strings should not be capitalized: e.g. fmt.Errorf("failed to send deployment message to queue: %w", err)


# Forms
The pattern / convention we have for forms is as follows:

1. Define a struct with the data captured by the form and the validation rules for each piece of data, e.g.:

type CreateAppFormData struct {
	AppName        string  `validate:"required,max=63,lowercasealphanumhyphen"`
	ContainerImage string  `validate:"required"`
	Replicas       int     `validate:"required,min=1"`
	ContainerPort  int     `validate:"required,min=1,max=65535"`
	CpuLimit       float64 `validate:"required,min=0.1"`
	MemoryLimit    int     `validate:"required,min=32"`
	EnvVars        string  `validate:"omitempty,dotenvformat"`
	CellId         string  `validate:"required,startswith=cell_"`
}

2. Define a templ component that renders the form and takes in the form data, field errors, and a submit error. The form should use hx-post to post the form, hx-disabled-elt to disable the submit button, hx-trigger to trigger on submit, hx-indicator to show a loading indicator, and hx-swap to swap the form with the response, e.g.:

templ CreateAppForm(teamId string, cells []store.Cell, data CreateAppFormData, errors form.FieldErrors, submitError error) {
	<form
		novalidate
		hx-post={ urls.NewApp{TeamId: teamId}.Render() }
		hx-disabled-elt="find button[type='submit']"
		hx-trigger="submit"
		hx-indicator="find .loading"
		hx-swap="outerHTML"
		class="grid grid-cols-[auto,1fr] gap-2 text-xs mt-4"
	>
		<label class="flex items-center justify-end">app name</label>
		<div class="flex items-center justify-start gap-2">
			<input
				type="text"
				name="AppName"
				class={ cls(inputClass(errors.Get("AppName")), "max-w-xs") }
				placeholder="my-app"
				value={ form.InputValue(data.AppName) }
				required
			/>
			if errors.Get("AppName") != nil {
				<div class="text-error">{ errors.Get("AppName").Error() }</div>
			}
		</div>
		...
		<div></div>
		<div class="flex items-center justify-start gap-2">
			<button type="submit" class="btn btn-primary btn-sm">Create App</button>
			<span class="htmx-indicator loading loading-ring loading-sm"></span>
		</div>
		<div></div>
		if submitError != nil {
			<div class="text-error">{ submitError.Error() }</div>
		}
	</form>
}

3. The endpoint that receives the form data should return the same templ component, passing in the form data, field errors, and a submit error, e.g.:

func (h *PostAppsNewHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // ...
	var f templates.CreateAppFormData
	inputErrs, err := form.Decode(&f, r)
	if inputErrs.NotNil() || err != nil {
		// send back the form html w/ errors
		if err := templates.CreateAppForm(teamId, cells, f, inputErrs, err).Render(ctx, w); err != nil {
			http.Error(w, fmt.Sprintf("error rendering template: %v", err), http.StatusInternalServerError)
		}
		return
	}
    // ... other logic to do further validation, create resources, etc.

	// Redirect to the dashboard on success
	middleware.AddFlash(ctx, fmt.Sprintf("app %s created successfully", f.AppName))
	w.Header().Set("HX-Redirect", urls.Home{TeamId: teamId, EnvName: urls.DefaultEnvSentinel}.Render())
	w.WriteHeader(http.StatusOK)
}

css
go
golang
javascript
makefile
shell
templ

First Time Repository

bare metal PaaS

Go

Languages:

CSS: 100.0KB
Go: 469.7KB
JavaScript: 171.2KB
Makefile: 3.4KB
Shell: 0.1KB
templ: 73.3KB
Created: 4/14/2024
Updated: 11/15/2024

All Repositories (1)

bare metal PaaS