Skip to content

Getting Started

This guide will walk you through creating your first Arcade application, from installation to deployment.

Before you begin, make sure you have:

  • Dart SDK (3.0 or higher)
  • A code editor (VS Code with Dart extension recommended)
  • Basic knowledge of Dart programming
Terminal window
dart create -t console my_arcade_app
cd my_arcade_app

Add Arcade to your pubspec.yaml:

dependencies:
arcade: ^<latest-version>

Then install the dependencies:

Terminal window
dart pub get

Create a simple server in bin/server.dart:

import 'package:arcade/arcade.dart';
Future<void> main() async {
await runServer(
port: 3000,
init: () {
// Define your routes here
route.get('/').handle((context) => 'Hello, Arcade!');
route.get('/api/health').handle((context) {
return {'status': 'ok', 'timestamp': DateTime.now().toIso8601String()};
});
},
);
}
Terminal window
dart run bin/server.dart

You should see:

Server running on port 3000

Visit http://localhost:3000 to see your server in action!

The runServer function is the entry point for your Arcade application:

await runServer(
port: 3000, // Port to listen on
init: () { // Initialization function
// Define routes, configure services, etc.
},
logLevel: LogLevel.info, // Optional: Set log level
);

Routes in Arcade follow a simple pattern:

route.<method>(path).<hooks>?.handle(handler);

For example:

// Simple GET route
route.get('/users').handle((context) => 'List of users');
// POST route with before hook
route.post('/users')
.before((context) {
// Validate request
return context;
})
.handle((context) async {
final body = await context.jsonMap();
// Create user
return {'created': true};
});

Every handler receives a RequestContext object that provides access to:

  • Request data (headers, body, parameters)
  • Response utilities
  • Route information
route.get('/users/:id').handle((context) {
final userId = context.pathParameters['id'];
final filter = context.queryParameters['filter'];
return {
'userId': userId,
'filter': filter,
'requestedAt': DateTime.now().toIso8601String(),
};
});
route.post('/api/users').handle((context) async {
final result = await context.jsonMap();
if (result case BodyParseSuccess(:final value)) {
// Process the JSON data
final name = value['name'];
final email = value['email'];
return {'id': 123, 'name': name, 'email': email};
} else {
context.statusCode = 400;
return {'error': 'Invalid JSON body'};
}
});
route.get('/api/protected').handle((context) {
final token = context.requestHeaders.value('authorization');
if (token == null) {
throw UnauthorizedException();
}
return {'secret': 'data'};
});
// Global error handler
overrideErrorHandler((context, error, stackTrace) {
if (error is UnauthorizedException) {
context.statusCode = 401;
return {'error': 'Unauthorized'};
}
context.statusCode = 500;
return {'error': 'Internal server error'};
});

To serve static files, create a public directory in your project root:

my_arcade_app/
├── bin/
│ └── server.dart
├── public/
│ ├── index.html
│ └── style.css
└── pubspec.yaml

Arcade will automatically serve files from the public directory.

Here’s a recommended project structure for Arcade applications:

my_arcade_app/
├── bin/
│ └── server.dart # Entry point
├── lib/
│ ├── controllers/ # Route handlers
│ ├── services/ # Business logic
│ ├── models/ # Data models
│ └── hooks/ # Reusable hooks
├── public/ # Static files
├── test/ # Tests
└── pubspec.yaml

Use environment variables for configuration:

import 'dart:io';
Future<void> main() async {
final port = int.parse(Platform.environment['PORT'] ?? '3000');
final dbUrl = Platform.environment['DATABASE_URL'] ?? 'localhost';
await runServer(
port: port,
init: () {
// Use dbUrl to connect to database
route.get('/').handle((context) => 'Server running on port $port');
},
);
}

Now that you have a basic Arcade server running, explore these topics:

If you run into issues:

  1. Check the API Reference
  2. Look at the example applications
  3. Open an issue on GitHub

Happy coding with Arcade!