Skip to content

Latest commit

 

History

670 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GoSX Studio

GoSX Studio is the web-editing admin portal for no-code, user-authored websites. It is the entire surface a site owner lives in day to day: canvas design, content, commerce, media, and settings back-office, all in one GoSX-rendered shell. Think Webflow-shaped — host-configured, GoSX-rendered, one editor, one back-office, one portal.

Reference deployments: Muddy Noni (commerce) and Pajaritos (school site).

Run a site without writing Go

go run m31labs.dev/gosx-studio/cmd/gosx-site

Open http://127.0.0.1:8080/admin and a three-question wizard asks what the business is called, what it does, and how people reach it. It then builds a real, published website — a bakery gets a menu and a visit page, a consultant gets services and about — which you edit and publish from there. Nothing else is required: no adapters, no host application, no configuration file.

  Visit your site      http://127.0.0.1:8080/
  Edit your site       http://127.0.0.1:8080/admin
  Saved in             ./data/site.db

Editing happens on the page itself. The canvas renders the same markup a visitor sees; click any text to change it, use the hover controls to move, copy, or delete a section, and press + between sections to add one. Changes save as you type and stay private until you press Publish — a live page keeps serving its published version while you work on the next one.

The server binds to localhost by default and refuses to listen on a public address unless you set -admin-password, so it never exposes an unprotected admin area by accident.

Every site gets a working contact form on its contact page. Messages land in the admin area's inbox — no mail server to configure.

Accounts

On a laptop with no -admin-password, the admin is open, as before. On a server, the password you start with unlocks one thing: the form at /admin/login that creates the owner account. After that, everyone signs in with an email and password, and the password on the command line is only a bootstrap.

People in the admin invites others by link, as an editor (writes and publishes, reads messages) or an admin (everything except handing over the site). Anyone can turn on two-step sign-in with an authenticator app under Account. Activity shows who did what, and can be downloaded.

Single sign-on

Settings → Single sign-on connects an OpenID Connect provider such as Google Workspace, Microsoft 365, Okta, or Keycloak. Register the site there with the redirect address https://yoursite.com/admin/sso/callback, paste the issuer address, client ID, and secret, and a "Sign in with…" button appears on the sign-in page. Someone whose email already has an account signs in as that account; someone from the allowed email domain gets an editor account; everyone else is turned away.

There is no SAML on the site's side, on purpose. A company that runs SAML (Okta, Entra ID, OneLogin, Keycloak) publishes the same directory as an OpenID Connect application in a few clicks, and that is what you connect.

Plans

A site run on its own has everything. A platform that hosts many sites starts each one with -features (or GOSX_SITE_FEATURES), a list such as blog,forms,stats,domain,team, and the parts left out disappear from the admin menu and answer with a short "not part of your plan" page. The names are blog, forms, shop (products, orders, bookings, downloads, subscriptions), stats, domain, team, staging, and sso.

A platform also sets -managed-by (its name), -domain (the owner's domain it connected), and -operator-token. The site then tells its owner to ask the platform about domains instead of walking them through DNS, and answers GET /platform/status (JSON) and GET /platform/export.zip (the full backup) to callers who present the token as a bearer token.

Review before publishing

Turn on Settings → Team → Publishing needs approval and editors' Publish button becomes Request review. Requests wait under Review, where an admin looks at the draft as visitors would see it, then approves and publishes it or sends it back with a note the editor sees in the editor. Anyone signed in can make a preview link for a draft from the editor's sidebar: it shows the current draft to whoever has it for three days, without an account.

Running it for a team

  • Locked sections. An admin can lock any block from its toolbar. Editors see it and cannot change or remove it; a save that touches a locked block is refused with an explanation.
  • Request logs and metrics. Every response carries an X-Request-ID, and each request is one JSON line on stderr (-log-requests=false to stop). /admin/metrics serves Prometheus counters and content gauges to a signed-in admin.
  • Privacy. Messages export as CSV, delete one by one or by age, and can expire automatically (Settings → Privacy). One click writes a plain-language privacy page for the owner to check and publish.

Use your own domain

Open Settings → Your own domain in the admin. Type the domain, add the two DNS records the screen shows, and press Check DNS now until it reports that the domain reaches the server.

For HTTPS, start the site with the -https flag. It then listens on ports 80 and 443, fetches a certificate from Let's Encrypt the first time someone opens the secure address, and renews it on its own:

gosx-site -https -data /srv/site/site.db -admin-password 'a long passphrase'

Certificates are cached in a certs folder beside the data file. Pass -public-ip to show the server's address in the DNS instructions when it cannot be detected.

Where the site lives

Everything is in one SQLite file, data/site.db by default, with pictures in an uploads folder beside it. A site that was started on an older version with data/site.json is moved into the database on the next start, and the JSON file is kept as site.json.migrated. Pass a .json path to -data to keep using the one-file snapshot instead.

Selling

Shop in the admin holds products with pictures, options, and stock. A product on sale appears at /shop and in the menu, and can be placed on any page with the Product block. Visitors fill a cart; to let them pay, connect Stripe under Settings → Payments:

  1. Paste your Stripe secret key.
  2. In Stripe, add a webhook endpoint for https://yoursite.com/stripe/webhook sending checkout.session.completed, and paste its signing secret.
  3. Set a flat shipping charge, a free-shipping threshold, the countries you ship to, and whether Stripe Tax works out tax.

Payment happens on Stripe's hosted page; card details never reach the site. Paid orders appear under Shop → Orders with the buyer's address, a link to the payment in Stripe for refunds, and a "Mark as sent" button.

A product is one of four kinds. Something you ship is the default. A download takes a file up to 100 MB; the buyer gets a link that works for seven days, on the thank-you page and in the receipt. A subscription charges every week, month, or year through Stripe; renewals and cancellations flow back through the webhook. An appointment offers time slots from the days, hours, and slot length you set; free appointments book without checkout, paid ones go through the cart. Bookings appear under Shop → Bookings, where you can cancel one.

Buyers have no passwords. The Your orders link in the footer asks for their email and sends a sign-in link good for thirty minutes; the page then shows their orders, downloads, and subscriptions, with a button that opens Stripe's billing portal to change or cancel a subscription. A visitor who is not ready can ask the cart page to email them a link to their cart; if they have not bought within two hours, one reminder goes out, and never a second. Both need an email transport (-mail).

Look, deeper

Beside the six palettes there is Custom: pick a background and a text colour and the rest of the palette is mixed from them. Headings can be quiet, regular, or big; the text column narrow, regular, or wide. Every picture has a size (full, wider than the text, medium, small), a shape (as it is, wide crop, square, round), a caption, and a link. For owners who know CSS, Settings → Your own CSS applies to every page and to the editor's canvas; imports and anything that isn't plain CSS are stripped.

Agents: the site is a set of tools

Everything the editor can do, an agent can do too. The site is agent-native in four ways.

Reading. Every public page is also Markdown: add ?format=md or send Accept: text/markdown. /llms.txt describes the site (pages, contact, shop) and /llms-full.txt carries every page as one Markdown file. No key is needed.

Editing. An admin makes a key under Agents (name it after what will use it, tick what it may do: read, write, publish, settings). With the key, an agent uses the same operations as the editor:

  • the JSON API at /agent/v1 (OpenAPI at /agent/v1/openapi.json, block schema at /agent/v1/schema);
  • MCP at /agent/mcp (Streamable HTTP, bearer key). Claude Code: claude mcp add --transport http my-site https://yoursite.com/agent/mcp --header "Authorization: Bearer gsk_…";
  • a stdio bridge for clients that lack HTTP MCP: gosx-site mcp -site https://yoursite.com -key gsk_….

Pages are lists of blocks in the shape the editor uses. PATCH /agent/v1/pages/{id} edits by index (replace, remove, insert, append, move); PUT replaces; POST /agent/v1/pages creates from a template or from blocks. Posts, products, pictures, the Look, presets, messages, and visitor counts have calls of their own. Every write is a draft until publish, every action is audited under the key's name, and a revoked key stops at once.

Building from nothing. A platform can pass -agent-key gsk_… (or GOSX_SITE_AGENT_KEY) so an agent can call POST /agent/v1/setup and build the whole site before anyone signs in.

Your browser's assistant (WebMCP). The editor and every admin page announce their tools to the browser through WebMCP. A browser with a built-in assistant can then work the editor for you: "add a pricing section with three plans", "publish this page", "make the look warmer". The tools act as you, with your permissions, and every change is a draft you can undo from History. Browsers without an assistant ignore them.

The first visit builds the whole site

A new site's first visit to /admin is a six-step wizard, and the answers become the site:

  1. Your business. Name, a one-line tagline (search results and shares), and two or three sentences about you (the About page and the hero).
  2. What you do. Food, services, shop, portfolio, community, or something else. This picks the pages and the words.
  3. What you offer. Three things, each with a line and an optional price. They become feature cards on the home page, the menu or services page, and a pricing page when priced.
  4. Where and when. Email, phone, address, opening hours (a plausible week to correct, or "we don't have hours"), Instagram and Facebook. They fill the contact page, the hours and map sections, the footer, the header button (Call us / Email us), and what Google shows.
  5. Your look. Three starting points for colours and type.
  6. Your pages. What a business like yours usually needs is ticked: Home and Contact always, the kind's own page, About, a privacy policy kept out of the menu; Photos, Questions, and Pricing to opt into. "Publish everything now" is on; untick it to keep drafts.

On a hosted site the wizard is followed by the one-time password from the welcome mail, which creates the owner's account. Then the dashboard opens on Your site is ready: every page with its state and an Edit link, the live address, and the next few things to do.

Backdrops: generative, yours, and easy to calm

Any section band and any hero can carry a backdrop: a generative picture drawn live on a canvas behind the words. Eight kinds: Aurora (soft drifting colour), Particles (drifting points that link up), Waves, Orbs (lit spheres in depth), Grid (a floor to the horizon), Stars (a parallax field), Contours (a slowly breathing map), and Ribbons (twisting bands in depth). There is nothing to download: they draw from your own palette, so changing the Look changes every backdrop.

Every backdrop has a variation. New sites get one seeded from their name, so no two sites look alike and yours always looks like itself. Shuffle gives you another. Each has Motion (moving, slow, still), Strength (subtle, normal, bold), and a band can add Depth, which makes its cards lean toward the pointer.

Two hero layouts are built for them: Poster (big type over a full backdrop) and Stage (centred on a floor).

In the Look, Motion sets the whole site to full, calm, or off. Visitors who ask their device for less motion always get a still picture, tabs in the background stop drawing, and a big screen never costs more than it should.

Agents see the same choices in the schema (fx, motion, intensity, seed, depth on a section; effect, motion, intensity, seed on a hero).

Getting around the editor

Do anything. Press Ctrl+K (or click the box at the top) and type what you want: "pricing" adds a pricing section, "publish" publishes, "visit" opens the Visit page, "look" jumps to colours and fonts. Arrow keys choose, Enter does it.

Find a section. The sidebar has a search box; type "hours" or "map" and press Enter to add the first match.

Keyboard. Press ? for the sheet. Alt+↑ and Alt+↓ move the section you're in. Delete removes the selected section and offers Undo instead of asking "are you sure". Esc steps out of the text to the section. Ctrl+S saves now, Ctrl+Shift+P publishes.

Know where you are. Hover any section and its name shows at the top left: Hero, Pricing, Text. Every link field offers the site's own pages as you type.

Preview before you publish. The Preview button opens your draft exactly as visitors will see it, with a banner and a way back. View live opens what they see right now.

On a phone. The editor fits a phone: the sidebar becomes a drawer behind the + Add button, and every tool works with a thumb.

First time. Three tips sit above the page until you say Got it.

Rearranging, spacing, and presets

Every card, plan, question, person, row, and gallery picture has a small toolbar when you hover it. Drag the ⠿ handle to move it, or use the ↑ and ↓ buttons. The page saves on its own.

Every block has a space choice in its toolbar: tight, normal, roomy, or extra room. Use it to pull two blocks together or to give a section air.

Got a section right? Click ★ Save as a preset and give it a name. It appears under Your presets in the sidebar of every page. Adding a preset drops in a copy; the copy is yours to change. Forget a preset with ✕; pages that used it keep their copies.

Press Ctrl+S (⌘S on a Mac) to save at once.

Pages carry the polish a visitor expects: a skip link for keyboard users, visible focus rings, smooth scrolling that respects reduced-motion settings, a browser theme colour that matches the Look, a print stylesheet, and FAQ rich results for search engines when a page has a questions section.

Header and footer

Settings → Brand now shapes the whole frame: an announcement bar across the top with an optional link, a standout button at the end of the menu ("Book a table"), a header that stays put while scrolling, the menu repeated in the footer, extra footer links, and social profiles drawn as icons. In the editor, "In the menu" on any page tucks it under another page as a drop-down; menus stay one level deep on purpose.

Ready-made sections

The editor's sidebar starts with whole sections, not just pieces: a hero, feature cards, testimonials, pricing, questions and answers, a call to action, numbers, people, opening hours, a picture beside text, a map, and plain space. Each drops in with sensible starter copy, is edited in place like everything else, has a Layout switch (centred, split, cards, one big quote, and so on), and repeated things (cards, plans, questions, people) have an add button and a remove button.

A section break sets the mood for everything beneath it: a plain, tinted, accent, dark, or picture background; left or centred text; narrow, normal, wide, or edge-to-edge width; compact, normal, or roomy spacing; and a jump-to name, so a button can link to #pricing.

Small things are adjustable too. Select any text and the floating toolbar aligns it left, centre, or right. A button can be solid, outlined, or just a link. Columns come in two or three. "Latest posts" and "From the shop" sections fill themselves from the blog and the shop and stay current.

Editing together

Two people can open the same page. Each sees the other's initials in the editor's top bar, and when one of them saves, the other's canvas refreshes with the new blocks. If that person is typing, the refresh waits for a pause and a note says who changed what. There is no merging: the last save wins, and History keeps every version.

Staging and publishing everything at once

Saving in the editor never changes what visitors see; publishing does. The Staging page lists every page and post with unpublished changes and publishes them one at a time or all together with one button.

To walk through the whole site with those changes in place, give it a staging address such as staging.yourbusiness.com on the Staging page and point that name at the server like the main domain. The staging address shows drafts, menus and all, under a banner. It opens only for people who have the link, which carries a key you can renew. Search engines are told to stay away, nothing is counted, and anything that writes or pays is sent to the real site.

Backups and export

Settings → Backups and export downloads the whole site as one zip: pages, posts, pictures, messages, forms, and visitor counts. A backup of the same kind is written once a day into a backups folder beside the data file, and the last fourteen are kept. Turn that off with -no-backups.

To restore, stop the site, unzip the backup, and start the site from the site.db inside it. Certificates are never included; HTTPS issues new ones.

Run it in a container

docker build -t gosx-site .
docker run -p 8080:8080 -v gosx-site-data:/data \
  -e GOSX_SITE_ADMIN_PASSWORD=change-me gosx-site

Pages, pictures, and messages all live in the /data volume. The admin password is required in a container because the server is reachable from the network; the image will not start without one.

cmd/gosx-site is the default host: it assembles the sitehost, cms, and hostruntime packages into a program that runs. Applications that need more control still configure the packages directly, as the reference deployments do. The default host is a floor, not a ceiling.

Earlier docs described Studio as "the authoring layer, intentionally separate from gosx-cms and gosx-admin." That framing is retired — the code moved past it. Studio is the portal; gosx-admin is a generic back-office toolkit dependency (Studio consumes only gosx-admin/blockstudio); the former gosx-cms content-storage module is folded into this module as cms/* (see docs/ARCHITECTURE.md §"Release model" and cms/PROVENANCE.md for the fold-in record). The standalone m31labs.dev/gosx-cms repository is frozen and tombstoned as of its final v0.2.1 tag; new code should import m31labs.dev/gosx-studio/cms/....

What hosts provide vs. what Studio provides

Hosts supply adapters, persistence, permissions, routes, and copy. Studio supplies contracts, chrome, panels, canvas engines, back-office pages, and runtime islands.

Concretely, the host application supplies:

  • content adapters
  • shell labels, modes, panels, and resource links
  • permission adapters
  • server actions
  • route bindings
  • product copy
  • feature flags
  • design tokens

Studio supplies:

  • .gsx surfaces for visible editor UI
  • GoSX engines for heavy client-side interactions
  • GoSX islands for focused reactive controls
  • extension points for plugins
  • common authoring language for non-technical operators

Package map

The module is a strict import DAG: core sits at the bottom, shell composes everything above it, and peers never import each other. See docs/ARCHITECTURE.md for the full diagram.

Package Responsibility
core Pure data contracts and defaults: the site-map/canvas/composition/flow/engine/resource type system, zero UI or host imports.
authoring The typed server-action mutation boundary: operations, form codec, adapter interface, action handler, authoring surface assembly, and the style/appearance/section-field mutation family.
hostruntime Embedded runtime assets, bundle concatenation, and the public /_gosx/studio/* paths and HTTP mounting.
canvas Page-canvas engine hosting and server-rendered surface markup (artboards, thumbnails, block-layout DOM contract).
sitemap The visual site-map board: graph engine render, board/view projections, authoring panels/forms, site navigator.
panels Editor inspector/designer panels and their .gsx islands (right/left rail content units).
backoffice The CRUD portal surfaces — dashboard, per-domain index/detail pages, media library, settings, search, storefront preview. First-class per the portal definition.
shell The portal shell: host-facing ShellConfig/Shell/Store contracts, readiness rail, workbench chrome renderers, and the editor workbench composition root.
*runtime islands (fieldruntime, selectionruntime, workbenchruntime, styleruntime, previewruntime, blocklayoutruntime, brandruntime, inspectorruntime, sitemapruntime, authoringruntime, inlineeditruntime, canvas*runtime) The go:embed browser-runtime bundles the shell/canvas/sitemap/panels packages mount — one package per engine's client-side JS/WASM surface.
plugins/showcase3d The CMS/Studio contract for source photos, generated model artifacts, provenance, moderation, lifecycle readiness, no-code placement controls, and Scene3D viewer descriptors.
studio (root) Deprecated compatibility facade — type aliases and forwarding wrappers only, no logic. See "Versioning & compatibility" below.
cms/{blocks, content, flows, lifecycle{,/sqlstore}, media, render, store{,/file,/memory}, style} Folded-in content storage: block catalogs, revision/draft/publish lifecycle, media assets, generic block rendering, and CMS store contracts (+ in-memory/file/sqlite-backed implementations). Bottom tier — stdlib, gosx, gosx-admin only, zero imports of cms/studio or the root facade. See cms/PROVENANCE.md.
cms/studio (+ cms/studio/collab) Folded-in portal UI (three-pane authoring shell model, canvas/preview/panels/actions, realtime collaboration) that used to live in the standalone gosx-cms module. Top tier — imports cms/{lifecycle,flows,style} and cms/studio/collab; nothing in this module imports cms/studio back (that would close a cycle through the facade — see ARCHITECTURE.md). Ships its own forked runtime assets — see "Release model" below.

Quick start

  1. Mount the embedded runtime assets and stylesheet: hostruntime.MountRuntimes / hostruntime.DefaultRuntimeConfig.
  2. Configure the portal shell: shell.ShellConfig / shell.DefaultShellConfig (labels, modes, panels, resource links, engine globals, feature flags).
  3. Wire the mutation boundary: authoring.AuthoringActionHandler against your authoring.AuthoringAdapter implementation.
  4. Render the editor route with shell.RenderBackendEditorPage, and the CRUD routes with the backoffice package's per-domain Render* pages.

The canonical host adapter is muddy-noni-commerce's internal/studiohost/adapter.go, which builds a hostruntime.RuntimeConfig and shell.ShellConfig (host labels, resource links, panels, actions) end to end.

Versioning & compatibility

The root studio package is a deprecated compatibility facade for one release cycle (v0.6.x): every symbol muddy, pajaritos, and cms/studio (the former gosx-cms/studio) used before the package restructure still resolves through a type alias or thin forwarding wrapper, each marked // Deprecated:. New code should import the subpackages above directly (core, authoring, shell, canvas, sitemap, panels, backoffice, hostruntime) rather than the root.

The gosx-cms module fold-in (previously "Phase 2") landed: all 13 gosx-cms packages now live under cms/ in this module, and gosx-studio's own go.mod no longer requires gosx-cms — see docs/ARCHITECTURE.md §"Release model" for the folded DAG shape and cms/PROVENANCE.md for the path mapping and source commit.

See docs/WEBFLOW_CLASS_EDITOR_GAP_INVENTORY.md for the detailed gap inventory and work plan toward a Webflow-class no-code editor.

About

GoSX website customization and authoring layer for no-code site Studio surfaces

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages