Skip to content
Atelierby Alto Brio
Documentation navigation

Atelier 0.7.0

Customize your application

On this page

Start from a working local demo and choose one visible outcome: your own identity, an extra project field or a new workflow. Use fictional data while developing. Keep a local copy of the acquired sources and original SOURCE-MANIFEST.json so you can distinguish the delivered kit from your changes.

These instructions assume the repository's Node.js 24.22.1–24.x, npm 11 and PostgreSQL 18 toolchain. Commands run from the folder containing package.json.

Keep your application in a private repository

From the Git checkout described in Get the sources, create an empty private repository for your application. If an existing clone calls the kit remote origin, first rename it with git remote rename origin atelier. For an archive, initialize Git with git init -b main, then review and commit the extracted files.

Set the URL of your empty private application repository and add it as origin:

APPLICATION_REPO='https://github.com/YOUR_ACCOUNT/YOUR_PRIVATE_REPOSITORY.git'
APPLICATION_REMOTE_READY=
git remote add origin "$APPLICATION_REPO" &&
test "$(git remote get-url --all origin)" = "$APPLICATION_REPO" &&
test "$(git remote get-url --push --all origin)" = "$APPLICATION_REPO" &&
git remote -v &&
APPLICATION_REMOTE_READY="$APPLICATION_REPO"

Run the block together. If it fails, stop and resolve the remote configuration before continuing. Check that the output shows your private application URL for both fetch and push under origin; a kit clone also has atelier for kit updates. After checking, run this block in the same terminal to verify the destination again and push main:

test -n "$APPLICATION_REPO" &&
test "$APPLICATION_REMOTE_READY" = "$APPLICATION_REPO" &&
test "$(git remote get-url --all origin)" = "$APPLICATION_REPO" &&
test "$(git remote get-url --push --all origin)" = "$APPLICATION_REPO" &&
git push -u origin main

Change the application identity

Edit src/branding.ts. For example:

export const appBrand = {
  name: 'Fieldwork',
  description: 'A workspace for client engagements.',
  demoDescription: 'Local demonstration of the Fieldwork workspace.',
  logo: '/brand/logo.svg',
};

Replace public/brand/logo.svg with an asset you have the right to use, or update logo to a new path under public/. The leading slash is the browser path: /brand/logo.svg refers to public/brand/logo.svg. These values control shared identity and page metadata; they do not rewrite every screen. Review the sign-in introduction in identity-panel.tsx (src/app/_workspace/identity-panel.tsx) and the workspace copy for your audience.

Change colors and radii in src/styles/theme.css. For example, update both --primary and --ring for your accent, then check text contrast and keyboard focus. Use semantic classes such as bg-primary, text-muted-foreground and border-border in new UI. Compose the editable components in src/components/ui/ instead of creating a second set of button and form styles. Local fonts and page metadata are set in src/app/layout.tsx.

Verify the sign-in and signed-in screens at narrow and wide widths, including keyboard navigation, validation errors and pending actions. Public email uses its EMAIL_FROM_NAME when set, falling back to appBrand.name when it is absent. The public runtime template sets EMAIL_FROM_NAME explicitly; update it through configuration. The supplied page metadata disables indexing. Review that deliberately if your product needs searchable public pages.

Add a project field from form to storage

The workspace interface is in src/app/_workspace/, server code in src/server/, schema migrations in db/migrations/ and tests in tests/. Operating commands are under scripts/hosted/.

Suppose your product needs an optional delivery date. Decide first whether it is a date or timestamp, whether past dates are allowed, who can set it and what an empty value means. The current example creates and archives projects; an edit screen would be a separate addition.

Implement the field through the whole path:

  1. Add a higher-numbered NNN_name.sql file in db/migrations/. Read the current migration filenames, migration runner (src/server/db/migrations.ts) and migration tests (tests/integration/migrations.ts) first. For an optional calendar date, a nullable date column can preserve existing rows without inventing a date for them. Never edit an applied migration or its checksum.
  2. Extend the input and response schemas in src/contracts/projects.ts. Validate untrusted values on the server, including invalid dates and unknown fields; a browser input alone is insufficient.
  3. Trace the request from the project route (src/app/api/teams/[teamId]/projects/route.ts) through src/server/http/workspace.ts and src/server/projects-core.ts. Add the stored value and include it in the workspace read response. Keep the owner's team, active plan and quota checks in the transaction that performs the write.
  4. Extend projects-panel.tsx (src/app/_workspace/projects-panel.tsx) and its command input. Display the saved value after refresh and preserve a user's input when a request fails. Keep confirmation and read-retry behavior: a failed refresh must not automatically repeat a creation.
  5. Inspect src/server/data/operations.ts and data contribution tests (tests/integration/data-contributions.ts). Account for the new field in eligible erasure and in any data-export workflow you implement; the kit does not supply a complete export workflow. For a new table, also decide its ownership, foreign keys and treatment of retained shared data. The kit does not detect tables omitted from your erasure handling; test which added records are removed and which remain.
  6. Extend the existing project and browser scenarios for valid input, invalid input, persistence after reload, another team's data and member refusals. Exercise both a fresh schema and applying the migration to populated data.

With this copy's server stopped, apply your migration to the dedicated local development database and check it before trying the screen:

npm run db:migrate
npm run doctor -- --database
npm run dev

The migration runner rejects altered applied files, missing history and an occupied schema without the expected journal. Resolve the mismatch instead of changing the journal to make the check pass.

Change business rules deliberately

The supplied policy is owner-only project writes with an active team plan. If your product needs members to edit projects, changing a button is not enough. Change the server policy in src/server/access.ts and its policy/core helpers, then update the affected writes, interface and permission tests together. Verify both the newly allowed action and continued refusal across teams, inactive plans and concurrent requests.

Stripe offer labels and quotas belong in the configuration described in configuration. The demo's three-project default is not the source of a Stripe subscription's quota. Preserve existing subscriptions when changing offers: deleting their price from the configured catalog can block paid writes. Treat a new resource type or a different quota metric as a business-rule change that needs server enforcement and concurrency checks.

Add a page or endpoint

For a new page or endpoint, inspect src/proxy.ts, src/server/http/ and the HTTP extension tests (tests/verification/http-extensions.test.ts). Check access in its intended mode. Keep unknown input validated and secrets in server-only code. Do not expose the unrestricted Better Auth handler to add a provider or plugin; extend the controlled operations in src/server/auth/identity-api.ts.

If a feature sends a notification, record it in the transaction with the business change and let the worker dispatch it after commit. The existing queueBusinessEmail (src/server/email/business.ts) accepts a verified team recipient and a deduplication key; the caller still owns authorization. Handle recorded, duplicate and rejected results rather than equating enqueueing with delivery. It captures messages locally in demo mode. For asynchronous work and other cross-boundary changes, follow the change rules in your source copy (.agents/skills/kit-feature/references/change-rules.md).

Verify the change you made

Stop this copy's development server before type generation, tests or build: those commands share .next. Use the supplied runners, which coordinate their own resources. Do not stop another copy or remove a lock whose owner is unclear.

npm run quality:static
npm run test:integration -- --list
npm run test:browser -- --list

SQL and browser suites require an explicit TEST_DATABASE_URL selecting the postgres maintenance database on PostgreSQL 18 at 127.0.0.1 or localhost, with a username, password and permission to create temporary databases. Use your local server's credentials and port, with no query parameters. For example:

export TEST_DATABASE_URL='postgres://YOUR_USER:YOUR_PASSWORD@127.0.0.1:55439/postgres'

Replace the placeholders and URL-encode special characters in credentials. Do not use a hosted or customer database. The runner creates and removes its own temporary databases; it preserves the supplied PostgreSQL server. Browser suites also need Chromium: install the runner's version with npm run browser:install when needed.

Choose the affected suites from those lists. For the project-field example:

npm run test:integration -- --suite core
npm run test:browser -- --suite demo
npm run build

For schema changes, also select the migration suite shown by --list; for changes to identity, billing, email or data requests, select their affected suites. npm test runs verification and SQL suites. For a full check, including static checks, tests, coverage reports, build and browser suites, use:

npm run quality

To generate coverage reports without running the build and browser suites, run npm run test:coverage. Both commands measure server and operator code exercised directly by Node tests; execution inside the Next.js server does not contribute to these reports. Open the HTML reports under output/coverage/ to inspect uncovered paths and add tests for relevant missing cases.

The reference thresholds and file selection are defined in scripts/checks/coverage.json. Adapt its lines, branches, include or exclude values when your application's scope justifies a different target or selection. New files matching that selection enter the measurement automatically.

Add -- --check to either command, such as npm run quality -- --check, to fail when coverage falls below the configured thresholds. Without it, thresholds are reported for comparison; test failures and incomplete measurements still fail.

To retain verification logs and a machine-readable report under output/verification/, add --report to a verification command, for example npm run quality -- --check --report.

Keep sources stable during final checks, and rerun affected checks after later edits.

Work with an agent or update dependencies

Give an agent the desired user action, expected result, roles and plan states, plus what is outside scope. Have it start with AGENTS.md and the kit-feature skill in your source copy (.agents/skills/kit-feature/SKILL.md). Ask for the visible workflow, affected checks and any unverified integrations, not just a code diff. Keep reports and screenshots under ignored output/.

For dependency updates, compare the current pins in package.json and package-lock.json, migration history and affected contracts before applying changes. Read the installed Next.js documentation under node_modules/next/dist/docs/ before changing a Next.js API. Review third-party notices when adding or updating dependencies with npm run deps:notices, and use npm run deps:check for the dependency audit.

Integrate a kit update

Choose an eligible delivery from the private Atelier repository and read its release notes. Your accepted terms define update access. Keep the acquired sources, original SOURCE-MANIFEST.json and accepted terms with your project records.

In your application repository, start with your changes committed and main up to date. Replace RECEIVED_UPDATE_TAG with the delivery tag, without its refs/tags/ prefix, and create an update branch:

UPDATE_TAG='RECEIVED_UPDATE_TAG'
git switch -c "update/$UPDATE_TAG" main

For an application started from an archive, compare the acquired releases and apply the selected changes on this branch. For a kit clone, fetch and merge the delivery instead:

git fetch atelier --tags
git merge "$UPDATE_TAG"

Resolve conflicts on this branch, preserving your application changes.

If an incoming kit migration uses a number already taken by your own migration, compare its SQL and dependencies with your schema before integrating the update. The runner requires unique three-digit numbers, applies files in order and refuses new migrations before the last applied one. Keep every applied filename and its contents unchanged; do not alter checksums or the migration journal.

For incoming SQL that has not been applied to any installation you maintain, carry the still-needed transformations into new, unused higher-numbered migrations in your customized copy, preserving their dependency order. Check for overlapping columns, constraints and data changes rather than copying the SQL blindly. If installations have already applied different migrations under the same number, prepare a merge plan for those histories; there is no universal renaming or replay command that resolves the conflict.

Run npm ci to install the updated lockfile. Verify the resulting migration set both on an empty test database and on a populated test database representing your current schema and data. Run db:migrate, doctor -- --database and the affected suites described above; check that existing data and behavior survive and a second migration run applies nothing.

Complete the affected checks, try the changed user workflow and review the diff. Commit any conflict resolutions and adaptations on the update branch, then integrate it:

git switch main
git merge "update/$UPDATE_TAG"
git push origin main

For a hosted application, follow Deploy a later revision.