A collaborative, extensible whiteboard application built with Flutter. Works on web browsers and can be installed locally on desktop/mobile devices. Designed for easy testing and incremental feature development.
- Multi-Platform: Runs on web, desktop (Windows, macOS, Linux), and mobile (iOS, Android)
- Real-time Collaboration: Framework ready for multi-user sessions via WebSocket
- Extensible Architecture: Clean, modular code structure for easy feature additions
- Drawing Tools: Pen, eraser, and highlighter (easily extensible)
- Customization: Color picker and adjustable stroke width
- Undo/Redo: Full history management
- Modern UI: Material Design 3 with light/dark theme support
- Flutter SDK (version 3.0.0 or higher)
- Git
- For web: Modern web browser (Chrome, Firefox, Safari, Edge)
- For desktop: Platform-specific requirements (automatically handled by Flutter)
git clone https://github.com/Gabe1290/rouge.git
cd rougeflutter pub getFor Web:
flutter run -d chromeFor Desktop:
# macOS
flutter run -d macos
# Windows
flutter run -d windows
# Linux
flutter run -d linuxFor Mobile:
# iOS (requires macOS and Xcode)
flutter run -d ios
# Android
flutter run -d androidlib/
├── main.dart # App entry point
├── core/ # Core utilities and configuration
│ ├── config/
│ │ └── app_config.dart # App-wide configuration
│ ├── services/
│ │ └── websocket_service.dart # WebSocket service for collaboration
│ └── theme/
│ └── app_theme.dart # App theming
├── features/ # Feature modules
│ └── whiteboard/
│ ├── models/ # Data models
│ │ ├── drawing_point.dart
│ │ ├── drawing_tool.dart
│ │ └── stroke.dart
│ ├── providers/ # State management
│ │ ├── whiteboard_provider.dart
│ │ └── collaboration_provider.dart
│ └── widgets/ # UI components
│ ├── whiteboard_canvas.dart
│ ├── whiteboard_screen.dart
│ └── toolbar.dart
└── shared/ # Shared components
├── models/
└── widgets/
- Add to enum in
lib/features/whiteboard/models/drawing_tool.dart:
enum DrawingTool {
pen,
eraser,
highlighter,
line, // NEW TOOL
}- Update extension with tool properties:
String get name {
// ...
case DrawingTool.line:
return 'Line';
}-
Update toolbar in
lib/features/whiteboard/widgets/toolbar.dartto add icon. -
Update painter in
lib/features/whiteboard/widgets/whiteboard_canvas.dartif needed.
- Create a new model in
lib/features/whiteboard/models/:
// shape.dart
class Shape {
final ShapeType type;
final Offset start;
final Offset end;
final Color color;
final double strokeWidth;
}-
Update
WhiteboardStateto include shapes list. -
Add gesture handling in canvas widget.
-
Update painter to render shapes.
The framework is ready! To enable:
- Set up a WebSocket server (Node.js example):
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const rooms = new Map();
wss.on('connection', (ws, req) => {
const roomId = req.url.split('/').pop();
if (!rooms.has(roomId)) rooms.set(roomId, new Set());
rooms.get(roomId).add(ws);
ws.on('message', (message) => {
// Broadcast to all clients in room
rooms.get(roomId).forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});- Update WebSocket URL in
lib/core/config/app_config.dart:
static const String websocketUrl = 'ws://your-server.com:8080';- Uncomment connection code in
lib/core/services/websocket_service.dart:
// Remove the comment markers from the actual connection code
_channel = WebSocketChannel.connect(uri);- Add session joining in the UI:
// In whiteboard_screen.dart
final collaboration = ref.read(collaborationProvider);
await collaboration.joinSession('room-123');- Create a storage service in
lib/core/services/:
class StorageService {
Future<void> saveWhiteboard(List<Stroke> strokes) async {
final prefs = await SharedPreferences.getInstance();
final json = strokes.map((s) => s.toJson()).toList();
await prefs.setString('whiteboard', jsonEncode(json));
}
Future<List<Stroke>> loadWhiteboard() async {
final prefs = await SharedPreferences.getInstance();
final json = prefs.getString('whiteboard');
if (json == null) return [];
// Parse and return strokes
}
}-
Add save/load buttons to toolbar.
-
Call storage methods from provider.
Use packages like:
screenshot- Capture canvas as imagepdf- Generate PDFpath_drawing- Export as SVG
Example:
// Add to pubspec.yaml
dependencies:
screenshot: ^2.1.0
// Wrap canvas in Screenshot widget
Screenshot(
controller: screenshotController,
child: WhiteboardCanvas(...),
)
// Export
final image = await screenshotController.capture();Edit lib/core/config/app_config.dart to customize:
- WebSocket server URL
- Canvas size
- Stroke width limits
- Undo history size
- Reconnection settings
flutter testflutter test --platform chromeflutter test integration_test/flutter build web
# Output in build/web/flutter build macos
flutter build windows
flutter build linuxflutter build apk # Android
flutter build ios # iOS- Local Testing: Use ngrok to expose your local WebSocket server
- Cloud Deployment: Deploy WebSocket server to Heroku, AWS, Google Cloud, etc.
- Alternative: Use Firebase Realtime Database instead of WebSockets
Update pubspec.yaml:
dependencies:
firebase_core: ^2.24.2
firebase_database: ^10.4.0Replace WebSocket service with Firebase Realtime Database calls.
Potential features to add:
- Text tool
- Shape tools (rectangle, circle, arrow)
- Image insertion
- Layers
- Background patterns/grid
- Zoom and pan
- Export to PNG/PDF/SVG
- Persistent storage
- User cursors
- Chat
- Permissions (view-only, edit)
This is a personal project, but suggestions are welcome!
MIT License - Feel free to use and modify for your projects.
For issues or questions, please open an issue on GitHub.
Built with Flutter ❤️