Step 1 of 7

Tooling Prerequisites

Install Node.js via NVM, the ServiceNow SDK CLI, and Claude Code. These three tools are the entire foundation of the workflow.

Node.js via NVM

Install using NVM (Node Version Manager), not the direct Node installer — this avoids OS permission errors and lets you manage Node versions cleanly.

1. Install NVM
Open Terminal (Cmd+Space → "Terminal"). This downloads and installs NVM.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
2. Restart Terminal, then install Node 18
Close and reopen Terminal after the step above, then run both commands.
nvm install 18
nvm use 18
Download nvm-setup.exe from coreybutler/nvm-windows releases. Run the installer, then open Command Prompt and run: nvm install 18 then nvm use 18
Install CLIs
ServiceNow SDK
The official SDK CLI. Handles building, compiling TypeScript to XML, and deploying your app to ServiceNow — no browser clicking required.
npm install -g @servicenow/sdk
Claude Code
Your AI coding assistant in the terminal. You describe what you want, Claude writes the Fluent files for you and asks permission before touching anything.
npm install -g @anthropic-ai/claude-code

Verify all three tools are installed and reachable from your terminal:

ToolCommandExpected OutputMin Version
Node.js node --version v18.20.4 or higher v18.x.x
npm npm --version 9.x.x or higher 9.x.x
SN SDK now-sdk --version 4.4.x 4.4.x
Claude Code claude --version Any valid build string Latest
now-sdk: command not found after install?
This means the npm global bin folder isn't on your PATH. Find where npm installs globals, then add it to your shell config.
npm config get prefix
Take the output path (e.g. /Users/you/.nvm/versions/node/v18.20.4) and add /bin to your ~/.zshrc or ~/.bashrc:
export PATH="$(npm config get prefix)/bin:$PATH"
Then run source ~/.zshrc and retry.
First time running claude? It automatically opens your default browser and prompts you to log in with your Anthropic account. Once you approve the OAuth grant, it stores a session token locally — you won't need to authenticate again. If the browser window doesn't appear, check your terminal output for a manual auth URL you can open directly.
Step 2 of 7

Connect to Your Instance

Register your ServiceNow instance with the SDK once. Credentials are stored in your OS keychain — never in project files — so you never type a password again.

Find Your Instance URL

Your instance URL looks like: https://yourcompany.service-now.com

Using a Personal Developer Instance (PDI)? Log in to developer.servicenow.com to find your URL and credentials. You need admin role on the instance to deploy apps — verify you see "Admin" in the top-right corner of the ServiceNow UI.
Authenticate with Your Instance

The SDK stores credentials securely in your OS keychain — nothing is written to project files. Choose your authentication method below. Basic is the fastest to set up; OAuth is recommended for SSO environments, CI/CD pipelines, or shared team setups.

Step 1: Save Credentials
Run the command below, replacing <your-instance> with your actual instance name. The SDK will prompt you for your password.
now-sdk auth --add <your-instance>
Step 2: Understand the Flags
FlagPurpose
mydev A friendly alias for this connection — you’ll use this in other commands
Step 3: Verify It Works
If this runs without errors and starts downloading type definitions, your connection is working.
now-sdk auth --list
Expected output: dev → https://yourcompany.service-now.com (basic)
WARNING: Your password is stored in the OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) — NOT in any project file. Never create .env files with passwords.
Authentication failed? The most common causes are: (1) Your instance enforces SSO or MFA — use the OAuth tab instead, or ask your admin to create a dedicated service account with basic auth enabled under System Security → Users. (2) You have IP allowlisting on the instance — ensure your machine’s IP is permitted. (3) Your PDI instance is hibernating — log in to developer.servicenow.com and wake it up first.
When to use OAuth: OAuth uses token-based auth with automatic refresh. Required for SSO-enabled instances and recommended for production work.
Step 1: Install the ServiceNow IDE on Your Instance
This pre-configures the OAuth endpoint the SDK needs.
  1. Log into your ServiceNow instance as admin
  2. Open Application Manager (System Applications → All Available Applications → All)
  3. Search for "ServiceNow IDE" and install it
Step 2: Authenticate from the CLI
Run the command below, replacing <your-instance> with your actual instance name.
now-sdk auth --add <your-instance>
  1. The SDK prompts for the type of auth — choose OAuth
  2. Your browser opens the ServiceNow login page
  3. Sign in with your credentials (or SSO provider)
  4. After login, ServiceNow displays a one-time token in the browser
  5. Copy the token, paste it back into the terminal, press Enter
Step 3: Set as Default (optional)
OAuth tokens refresh automatically. You won’t need to re-authenticate unless the refresh token expires.
now-sdk auth --add mydev-oauth --type oauth --default
Step 4: Verify
Confirm the profile was saved with OAuth auth type before moving on.
now-sdk auth --list
Expected output: dev → https://yourcompany.service-now.com (oauth)
Step 3 of 7

Create & Scaffold the Project

Initialize the Society Management System project folder, scaffold the SDK structure, install dependencies, and pull type definitions from your instance.

Project Setup Sequence
1. Create & Enter Project Folder
mkdir SocietyMgmt
cd SocietyMgmt
2. Initialize SDK Project
The SDK prompts you for three things — use exactly these values:
now-sdk init
PromptEnter ThisWhy
App nameSociety Management SystemDisplay name in ServiceNow
Scope prefixx_societyNamespace to prevent conflicts with other apps
Auth aliasdevThe alias you registered in Step 2
3. Install Dependencies
Installs the SDK build tools, TypeScript compiler, and ESLint. This reads package.json and creates a node_modules/ folder. Expect 20–60 seconds on first run.
npm install
Success: added 312 packages, and audited 313 packages in 28s. If you see npm warn deprecated lines, those are safe to ignore — they come from the SDK’s own dependencies.
4. Fetch Type Definitions from Instance
Connects to your ServiceNow instance and downloads type declarations for every table, field, and API available to your scope. The TypeScript compiler uses these to validate your Fluent files — without them, every ServiceNow-specific reference will show as a type error and the build will fail.
npm run types
Takes 1–3 minutes on first run — it’s downloading declarations for thousands of platform tables. Progress is shown in the terminal. Types are written to a .types/ folder in your project and should be committed to git so teammates don’t need to fetch them individually.
Re-run this any time you: add a new table directly in the ServiceNow browser UI, modify an existing table’s columns outside the SDK, or upgrade the SDK to a new major version. Types go stale when the instance schema changes.
5. Initialize Git & Open in VS Code
git init
git add .
git commit -m "Initial project setup"
code .
Your Project Structure

After init, your project looks like this. You’ll add Fluent files under src/fluent/ in the next steps.

SocietyMgmt/
│
├── src/
│   └── fluent/               ← TypeScript files that DEFINE your app
│       ├── index.now.ts      ← Master export — every file must be listed here
│       ├── tables/           ← flat, maintenance_bill, service_request, visitor_log
│       ├── business-rules/   ← set-dates, prevent-double-booking
│       ├── script-includes/  ← SocietyUtils, MaintenanceBillingEngine
│       ├── scheduled-jobs/   ← mark-overdue-bills, generate-monthly-bills
│       ├── acls/             ← Security rules (resident, committee_member, admin)
│       └── navigation/       ← Sidebar menu items
│
├── package.json              ← Project settings and build commands
├── now.config.json           ← App identity (scope, name, scopeId)
└── .eslintrc                 ← Code quality rules
The Barrel File Rule: src/fluent/index.now.ts must export every Fluent file in your project. If you create a file and forget to add it here, that piece of your app will be silently skipped at deploy time — no error, just missing.
Step 4 of 7

Create AI Context Files

Start Claude Code and give it a briefing document. Without this, Claude starts each session knowing nothing about your project.

Launch Claude Code
Run from inside your project folder
Claude reads your project files automatically on startup and shows an interactive prompt.
claude
Prompt 1 — Create the Skill File

Think of a Skill file as a permanent cheat-sheet you hand Claude once. It tells Claude the name of your app, how to build and deploy it, and what the app actually does — so you never have to explain it again at the start of a new session.

The skill file is always unique to your project. The prompt below is tailored to the Society sample app we use in this guide. If you're building a different app, the skill file should reflect your tables, automation, and app context — not ours.

How we built this prompt: We asked Claude to inspect the project files and write the skill prompt itself. You can do the same for your own project — run Step A below first to let Claude generate a prompt tailored to your app, then use that output in Step B.
Step A — Ask Claude to build your skill prompt (skip if you're following the Society sample)

Paste this into Claude Code. It will inspect your project and output a ready-to-use skill prompt. Copy that output and use it in Step B.

Claude Code Prompt:
Look at my project's now.config.json, package.json, and src/ folder structure.

Then write me a Claude Code skill file prompt that captures:
1. My app identity (name, scope prefix, SDK version, auth alias)
2. The SDK build/deploy/types/transform commands and what each one does
3. Any file structure rules that are easy to get wrong (e.g. index exports, naming conventions)
4. My app's core tables, automation logic, and user roles

The skill file must be created at .claude/skills/<your-app-name>/SKILL.md (folder named after the app, file named SKILL.md in all caps).

Output only the prompt text — I'll use it in the next step to create the skill file.
Step B — Create the skill file

Paste the prompt Claude gave you in Step A (or copy the Society sample below if you're following this guide). Claude will read your project files and write the skill file automatically.

Following the Society sample? Just copy and paste — no editing needed. Claude reads your actual project files to fill in the real values.
Paste into Claude Code
Claude Code Prompt (Society sample reference):
Create a skill file at .claude/skills/society/SKILL.md for this project.

Read now.config.json and package.json to get the real app values, then write a
skill that covers:

1. Project identity: app name, scope prefix, SDK version, auth alias

2. SDK command reference:
   - npm run build: compiles TypeScript to XML, checks for errors, does NOT touch instance
   - npm run deploy: builds + pushes everything to ServiceNow
   - npm run types: fetches type definitions from instance (run when schema changes on instance)
   - npm run transform: pulls current instance state to local files (always commit first)

3. File structure rules:
   - Fluent files (.now.ts) define structure: tables, columns, ACLs, menus
   - Every Fluent file MUST be exported from src/fluent/index.now.ts
   - If you create a file and forget to export it, it will be silently skipped at deploy time

4. App context:
   Society & Apartment Management System (India-Focused).
   Replaces WhatsApp groups and Excel sheets with a proper ServiceNow app.

   4 core tables:
   - flat: master flat/unit registry — all other tables reference this
   - maintenance_bill: one record per flat per month, auto-generated by scheduled job
   - service_request: unified table for complaints, facility bookings, and notices
     distinguished by request_type choice field
   - visitor_log: gate entry log maintained by security staff

   Server-side automation:
   - Business Rule "set-dates": auto-fills opened_on on insert, resolved_on on resolve
   - Business Rule "prevent-double-booking": aborts facility booking if slot already taken
   - Script Include SocietyUtils: isSlotAvailable(), getUnpaidBillsByFlat(), getOpenRequestsByType()
   - Script Include MaintenanceBillingEngine: generateMonthlyBills(), markOverdueBills()
   - Scheduled Job (daily 1AM): marks unpaid past-due bills as overdue
   - Scheduled Job (monthly 1st): auto-creates bill records for all active flats

   Roles: resident, committee_member, admin.
What Claude will do after you paste this: It reads your project files, then creates a skill file at .claude/skills/society/SKILL.md. From that point on, every Claude session in this project automatically loads that file — Claude already knows your app without you saying a word.
Prompt 2 — Create the Field Reference (run after Step 5)

After the tables are built in Step 5, run this to generate a lookup doc at docs/field-reference.md. Claude can reference it in future prompts so it always uses the correct field names.

Claude Code Prompt:
Read the following Fluent files and create a reference document at docs/field-reference.md:
- src/fluent/tables/flat.now.ts
- src/fluent/tables/maintenance_bill.now.ts
- src/fluent/tables/service_request.now.ts
- src/fluent/tables/visitor_log.now.ts

For each table and each field include: short field name, full scoped field name,
data type, allowed values or max length, and a one-line plain English description.

Also document at the bottom:
1. request_type values and which fields are relevant to each:
   complaint → category, priority, assigned_to, vendor_name, resolution_notes
   facility_booking → facility, booking_date, start_time, end_time, charges
   notice → pinned, expires_on

2. Status workflows:
   Maintenance Bill: unpaid → paid | overdue (auto-set by scheduled job)
   Complaint: open → in_progress → resolved | rejected
   Facility Booking: requested → confirmed | cancelled
   Notice: active → expired (auto on expires_on date)

3. Script Include public methods:
   SocietyUtils.isSlotAvailable(facility, date, start, end) → boolean
   SocietyUtils.getUnpaidBillsByFlat(flat_sys_id) → GlideRecord
   MaintenanceBillingEngine.generateMonthlyBills(month_year) → void
   MaintenanceBillingEngine.markOverdueBills() → number of records updated
Step 5 of 7

Build the App with Claude

One prompt creates all Fluent files — 4 smart tables, 2 business rules, 2 script includes, 2 scheduled jobs, ACLs, and navigation. Review what Claude creates and approve each file.

What Gets Built
File CreatedTypeWhat It Does
tables/flat.now.tsTableMaster flat/unit registry — flat number, block, resident reference, ownership type (owner/tenant)
tables/maintenance_bill.now.tsTableMonthly maintenance billing — references flat, tracks amount, due date, payment status & mode
tables/service_request.now.tsTableUnified table for complaints, facility bookings, and notices via request_type choice field
tables/visitor_log.now.tsTableVisitor entry log — name, purpose, host flat reference, entry/exit timestamps, logged by security
business-rules/set-dates.now.tsBusiness RuleOn insert: auto-sets opened_on to today. On status→resolved: auto-sets resolved_on
business-rules/prevent-double-booking.now.tsBusiness RuleBefore insert/update on booking type: aborts if the same facility has a confirmed slot overlap
script-includes/SocietyUtils.now.tsScript IncludeHelpers: isSlotAvailable(), getUnpaidBillsByFlat(), getOpenRequestsByType()
script-includes/MaintenanceBillingEngine.now.tsScript IncludegenerateMonthlyBills(month_year) — creates bill records for all active flats. markOverdueBills() — flags unpaid past-due bills
scheduled-jobs/mark-overdue-bills.now.tsScheduled JobRuns daily at 1 AM — calls MaintenanceBillingEngine.markOverdueBills()
scheduled-jobs/generate-monthly-bills.now.tsScheduled JobRuns 1st of every month — calls MaintenanceBillingEngine.generateMonthlyBills()
acls/society-acls.now.tsACLsResidents read/create own records; committee_member can update all; admin can delete
navigation/app-menu.now.tsNavigationSidebar: Dashboard, My Bills, Complaints, Facility Booking, Notices, Visitor Log, Flat Registry
The Complete Build Prompt
Paste into Claude Code
This is a large prompt. Use Download as a .txt file so you can open and copy it easily.
Claude Code Prompt:
Create the complete Society Management System app in one pass.

Create the necessary Fluent files for every component below, then add each export to
src/fluent/index.now.ts. Scope prefix is x_society.

───────────────────────────────────────────────────────────────
TABLE 1 — flat  (master flat/unit registry)
───────────────────────────────────────────────────────────────
Purpose: single source of truth for every flat in the society.
Other tables reference this instead of storing flat_number as raw text.

Fields:
- flat_number: String max 10 chars, mandatory — e.g. A-101, B-204
- block: String max 5 chars — e.g. A, B, C
- floor: Integer — floor number
- resident: Reference to sys_user, mandatory — current resident
- ownership: Choice — owner, tenant. Default: owner
- move_in_date: Date
- contact_phone: String max 15 chars
- active: Boolean, default true — false when flat is vacant

───────────────────────────────────────────────────────────────
TABLE 2 — maintenance_bill
───────────────────────────────────────────────────────────────
Purpose: one record per flat per billing month.

Fields:
- flat: Reference to x_society_flat, mandatory
- month_year: String max 7 chars, mandatory — e.g. MAR-2026
- amount: Decimal, mandatory — charge in INR
- due_date: Date, mandatory
- status: Choice — unpaid, paid, overdue. Default: unpaid
- payment_date: Date
- payment_mode: Choice — cash, upi, bank_transfer, cheque
- remarks: String max 500 chars — committee notes

───────────────────────────────────────────────────────────────
TABLE 3 — service_request  (unified: complaints + bookings + notices)
───────────────────────────────────────────────────────────────
Purpose: single table for all resident requests and society communications,
distinguished by request_type.

Common fields (all types):
- request_type: Choice — complaint, facility_booking, notice. Mandatory.
- title: String max 200 chars, mandatory
- description: String max 4000 chars
- opened_by: Reference to sys_user, mandatory
- flat: Reference to x_society_flat
- opened_on: Date — auto-set by business rule on insert
- status: Choice — open, in_progress, resolved, confirmed, cancelled, active, expired
  Default: open
- assigned_to: Reference to sys_user — committee member

Complaint-specific fields:
- category: Choice — water, electricity, lift, parking, housekeeping, security, noise, other
- priority: Choice — low, medium, high. Default: medium
- vendor_name: String max 100 chars — outsourced vendor if any
- resolution_notes: String max 2000 chars
- resolved_on: Date — auto-set by business rule when status → resolved

Facility Booking-specific fields:
- facility: Choice — gym, community_hall, terrace, guest_room, swimming_pool
- booking_date: Date
- start_time: String max 5 chars — e.g. 10:00
- end_time: String max 5 chars — e.g. 14:00
- booking_charges: Decimal, default 0

Notice-specific fields:
- pinned: Boolean, default false
- expires_on: Date

───────────────────────────────────────────────────────────────
TABLE 4 — visitor_log
───────────────────────────────────────────────────────────────
Purpose: gate entry log maintained by security staff.

Fields:
- visitor_name: String max 100 chars, mandatory
- visitor_phone: String max 15 chars
- purpose: Choice — delivery, guest, service_vendor, cab, other
- host_flat: Reference to x_society_flat, mandatory
- vehicle_number: String max 15 chars
- entry_time: DateTime, mandatory
- exit_time: DateTime
- logged_by: Reference to sys_user — security staff

───────────────────────────────────────────────────────────────
BUSINESS RULE 1 — set-dates  (on service_request)
───────────────────────────────────────────────────────────────
Write a before-insert and before-update business rule on x_society_service_request.

It should handle two things:
- On insert: automatically populate opened_on with today's date if it is not already set.
- On update: when the status field changes to "resolved", automatically set resolved_on
  to today's date if it is not already populated.

Generate the appropriate ServiceNow server-side script for this logic.

───────────────────────────────────────────────────────────────
BUSINESS RULE 2 — prevent-double-booking  (on service_request)
───────────────────────────────────────────────────────────────
Write a before-insert and before-update business rule on x_society_service_request.
It should only run when request_type is "facility_booking" and status is not "cancelled".

The rule must prevent a booking from saving if another confirmed booking already exists
for the same facility on the same date with an overlapping time slot.
If a conflict is found, abort the action and show a clear error message to the user.

Generate the ServiceNow server-side script that queries for conflicts and enforces this.

───────────────────────────────────────────────────────────────
SCRIPT INCLUDE 1 — SocietyUtils
───────────────────────────────────────────────────────────────
Create a server-side Script Include class called SocietyUtils (not client-callable).

It should expose three reusable helper methods:

1. A method to check if a facility time slot is available — takes facility, booking date,
   start time, end time, and an optional record sys_id to exclude (for update scenarios).
   Returns true if no confirmed bookings overlap with the given slot, false otherwise.

2. A method to get all unpaid or overdue maintenance bills for a given flat sys_id.
   Returns results ordered by due date ascending.

3. A method to get all open (unresolved/unarchived) service_request records for a given
   request_type. Returns results ordered by opened_on descending.

Generate clean, well-commented ServiceNow GlideRecord-based code for each method.

───────────────────────────────────────────────────────────────
SCRIPT INCLUDE 2 — MaintenanceBillingEngine
───────────────────────────────────────────────────────────────
Create a server-side Script Include class called MaintenanceBillingEngine (not client-callable).

It should expose two methods:

1. generateMonthlyBills(month_year): Takes a billing period string like "MAR-2026".
   Finds all active flat records and for each one checks if a maintenance_bill already
   exists for that month_year. If not, creates a new bill with status = unpaid and
   due_date set to the 10th of the following month.
   Log how many bills were created using gs.info with a [SocietyApp] prefix.

2. markOverdueBills(): Finds all maintenance_bill records that are still "unpaid"
   but have a due_date in the past. Updates their status to "overdue".
   Log how many records were updated using gs.info with a [SocietyApp] prefix.

Generate production-quality ServiceNow server-side code for both methods.

───────────────────────────────────────────────────────────────
SCHEDULED JOB 1 — mark-overdue-bills
───────────────────────────────────────────────────────────────
Name: "Society: Mark Overdue Bills"
Schedule: Daily at 01:00 AM
Write a short job script that instantiates MaintenanceBillingEngine and calls
markOverdueBills(). Generate the script.

───────────────────────────────────────────────────────────────
SCHEDULED JOB 2 — generate-monthly-bills
───────────────────────────────────────────────────────────────
Name: "Society: Generate Monthly Bills"
Schedule: Monthly, 1st of every month at 06:00 AM
Write a job script that resolves the current month and year into a "MMM-YYYY" string
and passes it to MaintenanceBillingEngine.generateMonthlyBills(). Generate the script.

───────────────────────────────────────────────────────────────
ACLs
───────────────────────────────────────────────────────────────
Apply across all four society tables:
ACL 1 — READ: Any authenticated user can read records.
ACL 2 — CREATE: Any authenticated user can create service_requests and visitor_log entries.
  Only committee_member or admin can create maintenance_bill and flat records.
ACL 3 — WRITE: committee_member or admin can update all records.
  Residents can only update their own service_request records (opened_by = current user)
  when status is still "open".
ACL 4 — DELETE: Only admin can delete any record.

───────────────────────────────────────────────────────────────
NAVIGATION
───────────────────────────────────────────────────────────────
Application menu: "Society Management" — visible to all authenticated users.

Menu items:
1. "Dashboard"          order 100 — all service_request records (overview)
2. "My Bills"           order 200 — maintenance_bill filtered by current user’s flat
3. "Complaints"         order 300 — service_request where request_type = complaint
4. "Facility Booking"   order 400 — service_request where request_type = facility_booking
5. "Notices"            order 500 — service_request where request_type = notice, pinned first
6. "Visitor Log"        order 600 — all visitor_log records
7. "Flat Registry"      order 700 — flat table (committee_member/admin role required)
Claude shows each file it plans to create and asks for approval before writing. Review each one — 8 files total. Once done, run the Field Reference prompt from Step 4 before deploying.
Step 6 of 7

Build & Deploy to ServiceNow

Exit Claude Code (Ctrl+C), then compile and push your app. Two commands — first build to verify no errors, then deploy to go live.

Step 1 — Build (compile only, nothing sent to instance)
Compile TypeScript → ServiceNow XML
Checks for errors. Does not touch your instance. Always run this before deploying to catch problems early.
npm run build
Success: ✔ Compiled 4 modules  ✔ No errors found  Build completed in 2.1s
Got an error? The message tells you the exact file and line. Copy it, paste into Claude: "Fix this build error: [paste error]". Then build again.
Step 2 — Deploy (builds + pushes to ServiceNow)
Deploy the app live
Internally runs build, packages everything into a ServiceNow Update Set, authenticates via the stored keychain alias, and uploads. Your app goes live.
npm run deploy
Success looks like:
✔ Table: x_society_flat
✔ Table: x_society_maintenance_bill
✔ Table: x_society_service_request
✔ Table: x_society_visitor_log
✔ BusinessRule: Set Dates on Insert/Resolve
✔ BusinessRule: Prevent Double Booking
✔ ScriptInclude: SocietyUtils
✔ ScriptInclude: MaintenanceBillingEngine
✔ ScheduledJob: Society Mark Overdue Bills
✔ ScheduledJob: Society Generate Monthly Bills
✔ ACL: x_society (8 rules)
✔ AppMenu: Society Management
✔ Deployed successfully in 24.3s
Other Useful Commands
CommandWhat It DoesWhen to Use
npm run typesRe-fetches type definitions from instanceWhen schema was changed directly in the ServiceNow browser UI
npm run transformPulls current instance state to local filesTo import changes made via Studio — always commit your local work first
Step 3 — Verify the Deploy in ServiceNow UI

Open your ServiceNow instance in a browser and run through these four checks. Each one confirms a different layer of the app landed correctly.

Check 1: App menu appears in the navigator
Log in to your instance → look for Society Management in the left sidebar. If it doesn't appear, type Society in the top filter field of the App Navigator. Menus sometimes take up to 30 seconds to appear after a fresh deploy.
Expected Menu ItemWhat It Opens
DashboardAll service_request records (overview)
My BillsMaintenance bills filtered to current user's flat
Complaintsservice_request where request_type = complaint
Facility Bookingservice_request where request_type = facility_booking
Noticesservice_request where request_type = notice, pinned first
Visitor LogAll visitor_log records
Flat Registryflat table (committee_member / admin role required)
Check 2: All four tables exist
App Navigator → search "Tables" → open System Definition → Tables. In the search bar at the top of the list, filter by x_society in the Label or Name column.
Expected — all four should appear:
x_society_flat  |  x_society_maintenance_bill  |  x_society_service_request  |  x_society_visitor_log
Check 3: Business rules are active
App Navigator → search "Business Rules" → open System Definition → Business Rules. Filter Name contains society. Both rules must show Active = true. If either shows inactive, open the record and toggle it on.
Expected: Set Dates on Insert/Resolve (active, on x_society_service_request)  |  Prevent Double Booking (active, on x_society_service_request)
Check 4: Scheduled jobs are registered
App Navigator → search "Scheduled Jobs" → open System Definition → Scheduled Jobs. Filter Name contains Society. Both jobs should be listed and active. You can click Execute Now on the overdue bills job to test it immediately.
Expected: Society: Mark Overdue Bills (daily, 01:00 AM)  |  Society: Generate Monthly Bills (monthly, 1st, 06:00 AM)
Check 5: ACLs are in place
App Navigator → search "Access Control" → open Security → Access Control (ACL). Filter Name contains x_society. You should see 8 rules covering read, create, write, and delete across the four tables.
If no ACLs appear, your instance may have the High Security plugin disabled. Go to System Definition → Plugins and verify com.glide.security_jump_start is active, then redeploy.
Step 7 of 7

Society Management System is Live!

Log in to ServiceNow and look for Society Management in the left sidebar. 4 tables, 2 business rules, 2 script includes, 2 scheduled jobs, menus, and ACLs — all live. No more WhatsApp chaos!

Smoke-test checklist — run through these to confirm everything works end-to-end:
#ActionWhat to Verify
1 Open Flat Registry → New → create a flat (e.g. A-101, Block A, Floor 1) Record saves without errors; flat appears in the list
2 Open Complaints → New → submit a complaint referencing that flat opened_on is auto-populated by the business rule — you should not need to fill it in manually
3 Change the complaint status to resolved and save resolved_on auto-fills with today’s date — confirms the second branch of the set-dates business rule
4 Open Facility Booking → New → book the community hall for today, 10:00–14:00 → save. Then create a second booking for the same facility and overlapping time The second booking is blocked with an error message — confirms the prevent-double-booking business rule is active
5 Navigate to Scheduled Jobs → find Society: Mark Overdue Bills → click Execute Now Job runs without error; any maintenance_bill records with a past due date and status = unpaid flip to overdue
6 Log out and log in as a test user without the committee_member or admin role User can see complaints but cannot update records that don’t belong to them — confirms ACL rules are enforced
Next steps: Switch to Claude Mastery (top-left toggle) to learn how to extend scripts, add email notifications, build a dashboard UI page, and configure hooks for automatic linting.
Step 1 of 5

Best Practice Project Structure

Claude operates in a loop: Plan → Write → Test → Fix. It requires a predictable and cleanly isolated folder structure to maintain architectural momentum without getting confused.

your-app-root/
.claude/
claude.md
reference.md
mcp.json
skills/
society/
SKILL.md
references/
tables.md
roles.md
server-automation.md
hooks/
lint-check.js
src/
index.now.ts
package.json

Why this structure?

The .claude/ directory acts as an isolated "brain" folder. By strictly separating AI rules, hooks, and subagent configs from your src/ logic code, you ensure the AI reads configurations deterministically on every launch without injecting AI metadata into your actual ServiceNow deployment bundles.

Never place logic code alongside project instructions.

Step 2 of 5

Core Agentic Layers

There are five critical components that dictact how Claude "thinks" and engages with the world outside of its prompt box.

claude.md
The Project Governor. Resides in `.claude/`. Dictates the absolute unbreakable rules of the application (e.g. "Never use Tailwind", "Always write tests"). Use when: Establishing permanent architectural tones.
skills/<usecase>/SKILL.md
Executable Workflows. Each usecase gets its own folder under skills/ containing a SKILL.md and an optional references/ subfolder. Use when: You want Claude to carry permanent project context across every session.
MCP Protocol
The External Bridge. A standardized connection allowing Claude to seamlessly read live SQL Databases, execute GitHub PRs, or ping internal Cloud APIs. Use when: Your AI needs live external context.
Subagents
Parallel Mini-Minds. Claude can secretly spin up smaller child agents to read massive files or hunt for errors in the background while main logic proceeds. Use when: Processing heavy contextual tracking.
Hooks & Plugins
Execution Modifications. Hooks are local scripts run natively on execution. Plugins are external node wrappers injecting logic securely. Use when: Modifying the project environment formatting dynamically.
Step 3 of 5

Context Files vs Prompts

Mastering token bandwidth: Knowing when to rely on a dynamic Prompt versus hardcoding data into Context Files will save API costs and prevent Hallucinations.

Dynamic Prompts

Conversational strings sent directly in the terminal interface currently used to tell the Agentic Loop what exact task to execute immediately.

  • When refactoring a single localized function or method.
  • When brainstorming or debugging a highly specific stack trace.
  • One-off instructions like "Push this to github with message X" that do not define application architecture globally.

Persistent Context (.md)

Hardcoded rules inside claude.md and skills/<usecase>/SKILL.md (with supporting references/) that the AI loops over and digests automatically to establish permanent truths.

  • Enforcing framework choices (e.g. Always use standard ServiceNow classes instead of custom wrappers).
  • Supplying large Vendor Documentation (e.g. Pasting SDK release notes for correct API consumption).
  • Global Linting Rules that must apply unilaterally to every file outputted.
The Overload Rule: Avoid turning claude.md into a dump. If the persistent context spans past 200 lines, abstract it into smaller SKILL.md files under skills/<usecase>/. Heavy context drowns out immediate prompt efficacy!
Step 4 of 5

Important Slash Commands

Utilize standard forward slashes to trigger massive system states instantly from the chat terminal.

Terminal Shortcut: Shift + 1 (Fast Bash Escape)
When using Claude CLI, press Shift + 1 to immediately drop back into standard Bash mode. Run your OS commands natively, then press Esc to return. Claude instantly sees your output!
Command Primary Usage & Scenario
/rename [name] Rename the active chat session (e.g., /rename header-bug-fix). Critical for pausing work on Friday and resuming exactly next week.
claude -r Bash execution. Presents an interactive terminal list of every previous chat session across the system to instantly resurrect and continue.
/btw [question] "By The Way". Asks a totally isolated question ("What is the git tag command?") that won't append to the current logic context tree. Press Space to instantly zip back.
/model Instantly switch the intelligence layer (e.g., jump from Haiku to Sonnet) on the fly mid-conversation when hitting a devastating code roadblock requiring more IQ.
/usage Monitors token consumption and quota limits, vital for Team/API scaling thresholds.
/insights Generates an incredibly rich visual HTML report tracking exactly how efficiently you are utilizing prompts vs context vs subagents.
/voice Enters Voice-Dictation mode. Hold Space to speak long complex architecture demands directly to Claude naturally.
/config Opens graphical CLI prompts setting deep system variables visually instead of manually editing raw OS json configurations.
Step 5 of 5

Setup & Configuration Guide

A comprehensive methodology on how to actually configure Skills, Context, and Hooks inside your Society Management project to successfully govern Claude.

Project Brain Setup
1. Building 'reference.md' (Global Context)
This file holds permanent ServiceNow-specific rules ensuring Claude writes accurate platform schema natively without trying to guess.
Use: Forcing Claude to always use `GlideRecordSecure` instead of regular `GlideRecord` preventing major instance security breaches.
Ask Claude to generate it:
I am deploying a 'Society Management System' via SN SDK. Create a '.claude/reference.md'. Add a strict rule: "All database table queries must use 'GlideRecordSecure()' to enforce ACLs immediately. All logging must explicitly use 'gs.info("[SocietyApp]")'."
2. Auto-Generate UI Modules
Prompt Claude to automatically construct frontend visual components linking directly to the backend strict architectures you downloaded in Step 1.
Use: Safely creates ServiceNow UI Pages and backend module hooks using your `sys_metadata` logic without making manual mistakes.
Ask Claude to generate it:
Referencing our 'society-mgmt' fluent-patterns.md rules, please build a scoped frontend UiPage showing a society dashboard: count of open complaints by category, unpaid maintenance bills this month, and today's facility bookings from 'x_society_*' tables.
3. Configuring Execution Hooks
Hooks are scripts that run automatically immediately after Claude modifies a file, ensuring local environment uniformity.
Use: Ideal for automatically firing Prettier / ESLint fixing tools immediately after Claude generates a new ServiceNow Business Rule locally.
Example post-hook execution in bash:
{
  "post-file-write": "npm run lint -- --fix" // Automatically fixes ServiceNow Fluent syntax spaces
}