DEV_WORKFLOW - nself-org/cli GitHub Wiki

Developer Workflow Guide

Complete step-by-step guide from nself init to a fully working application with authentication.

Goal: Get from zero to working auth in under 5 minutes.


Quick Start (5 Minutes)

# 1. Initialize project (30 seconds)
nself init --demo
cd demo-app

# 2. Build configuration (30 seconds)
nself build

# 3. Start all services (2 minutes)
nself start

# 4. Setup authentication (1 minute)
nself auth setup --default-users

# 5. Verify it works (30 seconds)
curl -k -X POST https://auth.local.nself.org/signin/email-password \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"npass123"}'

# โœ… You should get an access_token back!

That's it! You now have:

  • โœ… PostgreSQL database with auth schema
  • โœ… Hasura GraphQL API tracking auth tables
  • โœ… nHost authentication service
  • โœ… 3 staff users ready to use
  • โœ… Working login endpoint

Detailed Workflow

Step 1: Project Initialization

# Create a new project
nself init

# Follow the interactive prompts:
# - Project name: my-app
# - Base domain: local.my-app.com
# - Enable demo mode: Yes

What happens:

  • Creates .env file with your configuration
  • Sets up project structure directories
  • Configures all services (PostgreSQL, Hasura, Auth, Nginx, etc.)

Verify:

ls -la
# You should see: .env, docker-compose.yml (placeholder), etc.

Step 2: Build Configuration

nself build

What happens:

  • Generates docker-compose.yml with all services
  • Creates Nginx reverse proxy configuration
  • Generates SSL certificates
  • Sets up database initialization scripts
  • Creates service-specific configurations

Verify:

ls -la
# You should see: docker-compose.yml, nginx/, ssl/, postgres/
docker compose config --services
# Should list all services

Step 3: Start Services

nself start

What happens:

  • Starts all Docker containers
  • Waits for health checks
  • Shows service status
  • Reports any issues

Expected output:

โœ“ Starting services...
โœ“ PostgreSQL      (healthy)
โœ“ Hasura          (healthy)
โœ“ Auth            (healthy)
โœ“ Nginx           (healthy)

โœ“ 20/20 services running
โœ“ Health checks: 17/19 passing

๐ŸŽ‰ All services started successfully!

Verify:

nself status
# All services should show as running

nself urls
# Should list all service URLs

Step 4: Setup Authentication

This is the critical step that the old workflow was missing!

nself auth setup --default-users

What happens:

  1. Checks PostgreSQL is running
  2. Applies Hasura metadata (tracks auth.users, auth.user_providers, etc.)
  3. Creates 3 staff users:
  4. All with password: npass123 (development only!)
  5. Verifies auth service can query users

Expected output:

โ„น Auth Setup Wizard

โ„น Checking Hasura metadata...
โœ“ Hasura metadata configured
โ„น Creating default users...
โœ“ User created: [email protected]
โ„น User ID: 11111111-1111-1111-1111-111111111111
โœ“ User created: [email protected]
โ„น User ID: 22222222-2222-2222-2222-222222222222
โœ“ User created: [email protected]
โ„น User ID: 33333333-3333-3333-3333-333333333333
โœ“ Created 3 default users (password: npass123)
โ„น Verifying auth service...
โœ“ Auth service configured correctly!

โœ“ Auth setup complete!

โ„น Next steps:
  - Test login: curl -k https://auth.local.nself.org/signin/email-password
  - Create more users: nself auth create-user [email protected]
  - List users: nself auth list-users

Manual alternative:

# Interactive mode (prompts for confirmation)
nself auth setup

Step 5: Verify Authentication Works

# Test login via API
curl -k -X POST https://auth.local.nself.org/signin/email-password \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "npass123"
  }'

Expected response:

{
  "session": {
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "...",
    "expires_in": 900,
    "user": {
      "id": "11111111-1111-1111-1111-111111111111",
      "email": "[email protected]",
      "displayName": "Platform Owner",
      "metadata": {
        "role": "owner"
      }
    }
  }
}

Test GraphQL access:

# Query users via Hasura
curl -X POST http://localhost:8080/v1/graphql \
  -H "x-hasura-admin-secret: $HASURA_GRAPHQL_ADMIN_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"query":"{ users { id display_name metadata } }"}'

Expected response:

{
  "data": {
    "users": [
      {
        "id": "11111111-1111-1111-1111-111111111111",
        "display_name": "Platform Owner",
        "metadata": {"role": "owner"}
      },
      {
        "id": "22222222-2222-2222-2222-222222222222",
        "display_name": "Administrator",
        "metadata": {"role": "admin"}
      },
      {
        "id": "33333333-3333-3333-3333-333333333333",
        "display_name": "Support Staff",
        "metadata": {"role": "support"}
      }
    ]
  }
}

Additional Workflows

Creating More Users

# Interactive mode
nself auth create-user

# Non-interactive with flags
nself auth create-user \
  [email protected] \
  --password=SecurePass123! \
  --role=user \
  --name="New User"

Listing All Users

nself auth list-users

Output:

 id                                   | email              | display_name      | role    | email_verified | disabled | created_at
--------------------------------------+--------------------+-------------------+---------+----------------+----------+----------------------------
 11111111-1111-1111-1111-111111111111 | [email protected]    | Platform Owner    | owner   | t              | f        | 2026-02-11 10:00:00.000000
 22222222-2222-2222-2222-222222222222 | [email protected]    | Administrator     | admin   | t              | f        | 2026-02-11 10:00:01.000000
 33333333-3333-3333-3333-333333333333 | [email protected]  | Support Staff     | support | t              | f        | 2026-02-11 10:00:02.000000

Applying Custom Seeds

# Create a seed file
nself db seed create my_data local

# Edit the file: nself/seeds/local/001_my_data.sql
# Add your INSERT statements

# Apply all seeds
nself db seed apply

# List seed status
nself db seed list

Viewing Logs

# View logs for specific service
nself logs auth

# Follow logs in real-time
nself logs auth --follow

# View logs for all services
nself logs --all

Database Operations

# Interactive PostgreSQL shell
nself exec postgres psql -U postgres -d myapp_db

# Run SQL query
nself db query "SELECT * FROM auth.users"

# Database backup
nself db backup

# Database migration
nself db migrate up

Hasura Management

# Track auth tables (done automatically by auth setup)
nself hasura track schema auth

# Export current metadata
nself hasura metadata export

# Reload metadata
nself hasura metadata reload

# Open Hasura console
nself hasura console

Development Cycle

Making Changes

# 1. Make changes to code, configuration, etc.
vim .env

# 2. Rebuild if configuration changed
nself build

# 3. Restart affected services
nself restart

# Or restart specific service
nself restart postgres

Testing Changes

# Check service health
nself status

# View logs for debugging
nself logs <service>

# Test endpoints
nself urls

Resetting Environment

# Stop services
nself stop

# Complete reset (removes containers, volumes, networks)
nself destroy

# Start fresh
nself build && nself start

Connecting Frontend Applications

Option 1: External Frontend (Next.js, React, etc.)

# Add to .env
FRONTEND_APP_1_NAME=webapp
FRONTEND_APP_1_PORT=3000
FRONTEND_APP_1_ROUTE=app

# Rebuild nginx config
nself build

# Restart nginx
nself restart nginx

# Frontend will be available at: https://app.local.nself.org

Option 2: Frontend as Custom Service

# Add to .env
CS_1=frontend:next-js:3000

# Rebuild
nself build && nself start

Using Auth in Frontend

// Example: Login from frontend
const response = await fetch('https://auth.local.nself.org/signin/email-password', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    email: '[email protected]',
    password: 'npass123'
  })
});

const {session} = await response.json();
const accessToken = session.access_token;

// Use token for GraphQL requests
const data = await fetch('https://api.local.nself.org/v1/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${accessToken}`
  },
  body: JSON.stringify({
    query: '{ users { id display_name } }'
  })
});

Troubleshooting Common Issues

Auth Service Returns 500 Error

Error:

{
  "status": 500,
  "message": "field 'users' not found in type: 'query_root'"
}

Solution:

# Hasura hasn't tracked auth tables
nself auth setup
# or manually:
nself hasura track schema auth
nself hasura metadata reload

Services Not Starting

# Check Docker status
docker ps

# Check for port conflicts
lsof -i :80
lsof -i :443

# View detailed logs
nself logs --all

# Try fresh start
nself stop && nself start

Can't Connect to Services

# Verify services are running
nself status

# Check URLs
nself urls

# Test local DNS
ping api.local.nself.org

# On macOS, might need to add to /etc/hosts:
# 127.0.0.1 api.local.nself.org auth.local.nself.org

Seed Files Not Applying

# Check seed file location
ls -la nself/seeds/common/
ls -la nself/seeds/local/

# Check seed tracking
nself db seed list

# Force reapply (remove tracking first)
nself exec postgres psql -U postgres -d myapp_db -c "DELETE FROM nself_seeds WHERE filename = '001_auth_users.sql'"
nself db seed apply

Database Connection Issues

# Check PostgreSQL running
nself status | grep postgres

# Check database exists
nself exec postgres psql -U postgres -l

# Recreate database
nself db reset  # โš ๏ธ Destructive!

Production Deployment

Before Going to Production

  1. Change all default passwords:
# Create production users with strong passwords
nself auth create-user \
  [email protected] \
  --password=$(openssl rand -base64 24) \
  --role=owner
  1. Update environment variables:
# Edit .env for production
ENV=production
BASE_DOMAIN=yourdomain.com
AUTH_DEFAULT_PASSWORD=  # Remove default!
  1. Use real SSL certificates:
# Replace self-signed certs
nself auth ssl install /path/to/production-cert.pem
  1. Enable monitoring:
# Add to .env
MONITORING_ENABLED=true
nself build && nself start
  1. Set up backups:
# Configure automated backups
nself db backup --schedule daily

Best Practices

Security

  • โœ… Always change default passwords
  • โœ… Use environment-specific .env files
  • โœ… Never commit .env to git
  • โœ… Use strong passwords in production
  • โœ… Enable rate limiting
  • โœ… Use real SSL certificates

Development

  • โœ… Use nself db seed apply for test data
  • โœ… Version control your seed files
  • โœ… Use migrations for schema changes
  • โœ… Test with realistic data volumes
  • โœ… Monitor logs during development

Deployment

  • โœ… Test in staging first
  • โœ… Use environment-aware seeding
  • โœ… Enable monitoring and alerting
  • โœ… Configure automated backups
  • โœ… Document custom configurations

Next Steps


Questions? Issues?

โš ๏ธ **GitHub.com Fallback** โš ๏ธ