Setup Guide

This guide will help you set up the Abrianto development environment and get started with development.

Prerequisites

Before you begin, ensure you have the following installed:

Required Software

  • Node.js 18+ - JavaScript runtime
  • pnpm 8+ - Package manager (recommended) or npm/yarn
  • PostgreSQL 15+ - Database server
  • Git - Version control
  • Docker & Docker Compose (optional) - For database development

Optional Tools

  • VS Code - Recommended IDE
  • Redis/Valkey - For caching (optional)
  • MinIO - For local file storage (optional)

Local Development Setup

1. Clone the Repository

git clone https://github.com/your-org/abrianto.git
cd abrianto

2. Install Dependencies

# Using pnpm (recommended)
pnpm install

# Using npm
npm install

# Using yarn
yarn install

3. Environment Configuration

Create a .env file in the root directory:

# Copy the example environment file
cp .env.example .env

Edit .env with your configuration:

# Database Configuration
DATABASE_URL=postgres://myuser:mypassword@localhost:5432/mydatabase

# Redis/Valkey (optional)
REDIS_URL=redis://localhost:6379

# Socketi (Pusher) Configuration
PUSHER_APP_ID=your_app_id
PUSHER_APP_KEY=your_app_key
PUSHER_APP_SECRET=your_app_secret
PUSHER_CLUSTER=us2

# Application Configuration
NODE_ENV=development
PORT=5173

# Multi-tenancy
DEFAULT_TENANT_ID=00000000-0000-0000-0000-000000000000

4. Database Setup

Using Docker (Recommended)

# Start database container
docker-compose up -d postgres

# Wait for database to be ready
docker exec -it abrianto-db-1 psql -U myuser -d mydatabase -c "SELECT 1;"

# Run migrations
npm run db:migrate

# Seed initial data (if provided)
npm run db:seed

Using Local PostgreSQL

  1. Create database:
createdb mydatabase
  1. Run migrations:
npm run db:migrate

5. Start Development Server

# Start the development server
npm run dev

# Start the development server and open browser
npm run dev -- --open

The application will be available at http://localhost:5173

6. Verify Installation

  1. Visit http://localhost:5173/docs in your browser
  2. Ensure the documentation page loads correctly
  3. Check the browser console for any errors
  4. Verify you can access the dashboard at /app

Development Workflow

Project Structure

abrianto/
├── src/
│   ├── routes/              # SvelteKit routes
│   │   ├── (app)/           # Authenticated app routes
│   │   ├── docs/            # Documentation
│   │   └── api/             # API endpoints
│   ├── lib/
│   │   ├── components/      # Reusable UI components
│   │   ├── server/          # Server-side logic
│   │   └── actions/         # Server actions
│   └── hooks.server.js      # Server hooks
├── db/
│   └── migrations/          # Database migrations
├── tests/
│   ├── unit/                # Unit tests
│   └── e2e/                 # End-to-end tests
└── package.json

Essential Commands

# Development
npm run dev              # Start dev server
npm run dev -- --open    # Start and open browser

# Database
npm run db:migrate       # Run migrations
npm run db:seed          # Seed database

# Code Quality
npm run lint             # Run ESLint and Prettier
npm run format           # Format code with Prettier
npm run check            # Type check with svelte-check

# Testing
npm run test:unit        # Run unit tests (watch mode)
npm run test:e2e         # Run e2e tests
npm run test             # Run all tests

# Building
npm run build            # Build for production
npm run preview          # Preview production build
npm run start            # Run production server

Database Management

Viewing Database Data

# Using psql
docker exec -it abrianto-db-1 psql -U myuser -d mydatabase -c "SELECT * FROM accounts LIMIT 10;"

# Query specific data
docker exec -it abrianto-db-1 psql -U myuser -d mydatabase -c "
  SELECT id, name, outstanding_balance, status
  FROM accounts
  WHERE tenant_id = '00000000-0000-0000-0000-000000000000'
  ORDER BY created_at DESC
  LIMIT 10;
"

Running Migrations

# Create new migration
mkdir -p db/migrations/YYYYMMDDHHMMSS_description
touch db/migrations/YYYYMMDDHHMMSS_description/index.sql
# Add migration SQL to index.sql

# Run migrations
npm run db:migrate

# Rollback last migration (if needed)
npm run db:migrate:rollback

Truncate Database

# WARNING: This will delete all data
DROP_ALL_TABLES_BEFORE_MIGRATION=true npm run db:migrate

Svelte 5 Development

Using Svelte Runes

<script>
	// State
	let count = $state(0);

	// Derived values
	let doubled = $derived(count * 2);

	// Side effects
	$effect(() => {
		console.log('Count changed:', count);
	});

	// Event handling
	function handleClick() {
		count++;
	}
</script>

<div>
	<p>Count: {count}</p>
	<p>Doubled: {doubled}</p>
	<button onclick={handleClick}>Increment</button>
</div>

Component Props

<script>
	let { title, count = 0 } = $props();
</script>

<h1>{title}</h1><p>Total: {count}</p>

Server Actions

// +page.server.js
import { json } from '@sveltejs/kit';
import { sql } from '$lib/server/db.js';

export async function load() {
	const accounts = await sql`
    SELECT * FROM accounts
    WHERE tenant_id = ${event.locals.tenant.id}
  `;
	return { accounts };
}

export const actions = {
	async createAccount(formData) {
		// Validation
		const data = Object.fromEntries(formData);

		// Database operation
		const result = await sql`
      INSERT INTO accounts (name, tenant_id)
      VALUES (${data.name}, ${event.locals.tenant.id})
      RETURNING *
    `;

		return json({ success: true, account: result[0] });
	}
};

Data Loading Pattern

// +page.server.js
import { sql } from '$lib/server/db.js';

export async function load({ params, url }) {
	const tenantId = event.locals.tenant.id;

	// Get filters from URL
	const status = url.searchParams.get('status');
	const page = parseInt(url.searchParams.get('page') || '1');
	const pageSize = 20;

	// Build query with dynamic conditions
	let query = sql`
    SELECT * FROM accounts
    WHERE tenant_id = ${tenantId}
  `;

	if (status) {
		query = sql`${query} AND status = ${status}`;
	}

	// Pagination
	query = sql`${query} ORDER BY created_at DESC LIMIT ${pageSize} OFFSET ${(page - 1) * pageSize}`;

	const accounts = await query;

	// Get total count
	const countQuery = sql`
    SELECT COUNT(*) FROM accounts
    WHERE tenant_id = ${tenantId}
  `;
	const [{ count }] = await countQuery;

	return {
		accounts,
		pagination: {
			page,
			pageSize,
			total: count,
			totalPages: Math.ceil(count / pageSize)
		}
	};
}

Testing

Unit Testing with Vitest

// src/lib/server/example.test.js
import { describe, it, expect } from 'vitest';
import { sql } from '$lib/server/db.js';

describe('Database queries', () => {
	it('should query accounts', async () => {
		const accounts = await sql`
      SELECT * FROM accounts
      WHERE tenant_id = '00000000-0000-0000-0000-000000000000'
    `;
		expect(accounts).toBeInstanceOf(Array);
	});
});

E2E Testing with Playwright

// e2e/accounts.spec.ts
import { test, expect } from '@playwright/test';

test('should display accounts page', async ({ page }) => {
	await page.goto('/app/accounts');

	// Wait for page to load
	await expect(page.locator('h1')).toContainText('Accounts');

	// Test table exists
	const table = page.locator('table');
	await expect(table).toBeVisible();
});

Run tests:

npm run test:unit       # Watch mode for unit tests
npm run test:e2e        # Run e2e tests
npm run test            # Run all tests

Development Best Practices

Code Quality

  1. Run linter before committing:

    npm run lint
  2. Format your code:

    npm run format
  3. Check types:

    npm run check

Component Development

  1. Always use Svelte 5 runes
  2. Use $props() for props, not export let
  3. Use onclick for events, not on:click
  4. Import components from lib/components/
  5. Follow existing patterns in the codebase

Database Queries

  1. Always scope queries with tenant_id
  2. Use tagged template literals
  3. Write queries using snake_case columns
  4. Access results using camelCase properties
  5. Use proper dynamic SQL patterns

API Development

  1. Add OpenAPI documentation comments
  2. Include error responses
  3. Handle pagination
  4. Add proper validation
  5. Include security headers

Troubleshooting

Common Issues

Database Connection Errors

# Check if database is running
docker ps | grep postgres

# Check database logs
docker logs abrianto-db-1

# Verify connection string
echo $DATABASE_URL

Port Already in Use

# Find process using port 5173
lsof -i :5173

# Kill process (replace PID)
kill -9 <PID>

Migration Issues

# Check migration status
docker exec -it abrianto-db-1 psql -U myuser -d mydatabase -c "SELECT * FROM schema_migrations;"

# Drop all tables and re-run
DROP_ALL_TABLES_BEFORE_MIGRATION=true npm run db:migrate

Import Errors

# Clear node_modules and reinstall
rm -rf node_modules pnpm-lock.yaml
pnpm install

# Clear pnpm store
pnpm store prune

Getting Help

  • Documentation: Visit /docs in the application
  • Issues: Report bugs on GitHub
  • Discussions: Join the community discussion
  • Email: support@abrianto.com

Next Steps

  1. System Architecture - Learn about the technical foundations
  2. Development Workflow - For developers building integrations
  3. API Documentation - Complete API reference

Happy coding! If you encounter issues, please check the troubleshooting section or reach out to support.