Skip to content

Repository files navigation

Scrollforge

Scrollforge is a multi-tenant website-building SaaS powered by the Scrollcraft design contract. A customer completes a structured interview, selects an engine, generates a static scroll-driven site, previews it safely, publishes it, and downloads a portable ZIP.

The supported generation engines are:

  • Scrollforge Studio: deterministic built-in generation, always available.
  • Claude Code: local CLI or authenticated remote runner.
  • Codex: local CLI or authenticated remote runner.
  • Hermes Agent: local CLI or authenticated remote runner.
  • AGY / Google Antigravity: local CLI or authenticated remote runner.

Every engine receives the same project skill at .agents/skills/scrollcraft, the same artifact schema, and the same server-side validation gates. Generated sites must use one grammar, a feeling-first journey, at least four device families, 8–14 viewport heights, exactly one peak, and an account-level fingerprint that differs on at least four of six dimensions.

Agent-assisted interview

On the new-project or edit-interview screen, paste at least 80 characters of About-page copy, a company profile, or sales notes into Start from your business profile. Choose any currently available engine and select Fill interview with agent.

The intake agent returns a separate structured draft for all 16 interview fields. Factual fields are grounded in the supplied profile; creative experience fields are marked as suggestions with confidence and source notes. Agent-filled answers are highlighted, existing answers are preserved unless replacement is explicitly selected, and no project is created or submitted until the user reviews and submits the form.

The authenticated endpoint is POST /api/intake/autofill with { "profile": "...", "engine": "builtin" }. The built-in intake is always available. Claude Code, Codex, Hermes, and AGY use the same local or remote engine configuration as website generation.

Connect your own agents

Open Engine connections in the studio sidebar to connect Claude Code, Codex, Hermes, or AGY independently. The browser never receives CLI credentials and cannot execute a local binary directly. Instead, run Scrollforge's authenticated runner on the trusted machine where the CLI is installed and signed in:

npm install
export ENGINE_RUNNER_TOKEN="$(openssl rand -hex 32)"export RUNNER_ENGINE_ALLOWLIST="claude,codex,hermes,agy"
npm run start:runner

Expose that runner through HTTPS, then paste the base URL and the same token into the matching engine card. Scrollforge calls the authenticated /v1/status endpoint before saving a connection, confirms that the selected CLI is installed and allowed, and then uses that personal runner for both profile autofill and website generation.

Set APP_SECRET to at least 32 random characters on the web service. Personal runner tokens are encrypted with AES-256-GCM before being written to SQLite, are tenant-scoped, and are never returned by the API. Runner connection probes require HTTPS, disable redirects, resolve and validate every address, reject non-public/private/local/metadata ranges, and pin the validated address for the TLS request.

Run locally

Requirements: Node.js 24 or newer.

npm install
cp .env.example .env
npm run dev

Open http://localhost:3000. Data is stored in .data/scrollforge.db; uploads and isolated job files live under .data/ as well.

Useful verification commands:

npm run check
npm audit --audit-level=high
VERIFY_URL=http://127.0.0.1:3000 npm run verify:browser
node scripts/engine-contract-smoke.mjs hermes

Engine modes

Each external engine supports auto, local, remote, or disabled:

CLAUDE_ENGINE_MODE=autoCODEX_ENGINE_MODE=autoHERMES_ENGINE_MODE=autoAGY_ENGINE_MODE=auto

auto prefers an installed local CLI and falls back to its runner URL. Optional model variables are CLAUDE_MODEL, CODEX_MODEL, HERMES_MODEL, and AGY_MODEL; Hermes also supports HERMES_PROVIDER.

Local engines

Install and sign in to the desired CLIs on the machine running Scrollforge. The server detects executables directly through PATH. Local jobs run in isolated directories and use non-interactive modes:

  • Claude Code: print mode with JSON Schema and plan permissions.
  • Codex: ephemeral, read-only codex exec with a schema-owned output file.
  • Hermes: one-shot mode with the scrollcraft skill explicitly preloaded.
  • AGY: headless plan mode, sandboxing, and JSON Schema output.

Remote runner

The runner lets the public SaaS stay on Railway while agent credentials remain on a trusted workstation, Hostinger VPS, or private server.

On the trusted runner host:

export ENGINE_RUNNER_TOKEN='replace-with-a-long-random-secret'export RUNNER_ENGINE_ALLOWLIST='claude,codex,hermes,agy'
npm run start:runner

Expose the runner only through HTTPS and restrict ingress where possible. Configure the public app with the same secret and one or more URLs:

ENGINE_RUNNER_TOKEN=replace-with-a-long-random-secretCLAUDE_ENGINE_MODE=remoteCLAUDE_RUNNER_URL=https://runner.example.comCODEX_ENGINE_MODE=remoteCODEX_RUNNER_URL=https://runner.example.comHERMES_ENGINE_MODE=remoteHERMES_RUNNER_URL=https://runner.example.comAGY_ENGINE_MODE=remoteAGY_RUNNER_URL=https://runner.example.com

GET /healthz is public on the runner. POST /v1/run requires the bearer token, enforces RUNNER_ENGINE_ALLOWLIST, and only accepts the server-owned website and intake-profile task schemas.

GET /v1/status also requires the bearer token and reports only engines that are both allowed and installed. The studio uses it for connection tests without spending an agent generation.

Railway deployment

The included Dockerfile runs the SaaS and stores all mutable state under /data.

  1. Create a Railway project and service from this repository.
  2. Attach a persistent volume mounted at /data.
  3. Set DATA_DIR=/data, NODE_ENV=production, a random APP_SECRET of at least 32 characters, and GENERATION_LIMIT_PER_MONTH as desired.
  4. Create a public domain, then set APP_ORIGIN to its exact HTTPS origin.
  5. Configure remote runner variables for any external engines that should be available in the hosted UI.

CLI equivalent after railway login:

railway up --new --name scrollforge --yes
railway volume add --mount-path /data
railway domain

After Railway returns the domain, set APP_ORIGIN=https://your-domain and redeploy. The service health endpoint is /healthz.

Hostinger deployment

On a Hostinger VPS with Docker, build the image, mount a durable host directory at /data, and put it behind HTTPS:

docker build -t scrollforge .
docker run -d --name scrollforge --restart unless-stopped \
-p 127.0.0.1:3000:3000 \
-v /srv/scrollforge-data:/data \
--env-file .env \
scrollforge

If the same VPS also runs authenticated agent CLIs, run npm run start:runner as a separate locked-down service rather than placing CLI credentials in the public app container.

Security and tenancy

  • Passwords use salted scrypt hashes; session cookies are HTTP-only, same-site, and secure in production.
  • Projects, jobs, assets, fingerprints, previews, and exports are scoped by the authenticated user.
  • Generated markup is checked for executable HTML and unsafe closing tags.
  • Previews and published sites use CSP sandboxing with an opaque origin, preventing generated JavaScript from calling the SaaS API with user credentials.
  • Uploaded filenames are normalized and stored outside the public directory.
  • Engine runner requests require a constant-time bearer-token comparison.
  • Personal runner tokens are tenant-scoped and encrypted at rest with AES-256-GCM; APIs return connection metadata but never return tokens.
  • User-provided runner URLs require HTTPS and are checked against private, local, reserved, and cloud-metadata address ranges before a DNS-pinned request with redirects disabled.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages