feat: Integrate Docusaurus for documentation and enhance project structure

- Added Docusaurus configuration and initial setup for documentation.
- Created multiple documentation pages covering installation, configuration, and core concepts.
- Implemented a GitHub Actions workflow for automatic deployment of documentation to GitHub Pages.
- Updated .gitignore to exclude Docusaurus build artifacts and dependencies.
- Enhanced README with a link to the online documentation.
This commit is contained in:
StarFleetCPTN
2025-04-12 13:01:53 -07:00
parent 0aa68bc8e7
commit 834f066704
90 changed files with 24649 additions and 15 deletions
+55
View File
@@ -0,0 +1,55 @@
name: Deploy Docusaurus to GitHub Pages
on:
push:
branches: [main]
paths: ['docs/**']
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
build:
name: Deploy Docusaurus
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./docs
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: yarn
cache-dependency-path: docs/yarn.lock
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build
run: yarn build
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: ./docs/build
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
+11
View File
@@ -71,3 +71,14 @@ static/dist/
# Ignore binaries
gomft
# Docusaurus files
docs/.docusaurus/
docs/.cache-loader/
docs/build/
docs/build-searchindex/
docs/static/search/
docs/static/js/
docs/node_modules/
docs/.env*
docs/*.log
+3
View File
@@ -10,6 +10,9 @@ GoMFT is a web-based managed file transfer application built with Go, leveraging
<a href="https://discord.gg/f9dwtM3j">
<img src="https://img.shields.io/discord/1351354052654403675?color=7289da&logo=discord&logoColor=white&label=Discord" alt="Join our Discord server!" />
</a>
<a href="https://starfleetcptn.github.io/GoMFT/">
<img src="https://img.shields.io/badge/docs-online-blue.svg" alt="Documentation" />
</a>
</p>
> [!WARNING]
+20
View File
@@ -0,0 +1,20 @@
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+47
View File
@@ -0,0 +1,47 @@
# GoMFT Documentation
This repository contains the documentation for [GoMFT](https://github.com/StarFleetCPTN/GoMFT), a modern, web-based managed file transfer solution written in Go.
[![Discord](https://img.shields.io/discord/1351354052654403675?color=7289da&logo=discord&logoColor=white&label=Discord)](https://discord.gg/f9dwtM3j)
## Getting Started
### Installation
```bash
# Install dependencies
npm install
# Start the development server
npm run start
```
### Build
```bash
# Build the static site
npm run build
```
The built files will be in the `build` directory.
## Documentation Structure
- **Introduction**: Overview and features of GoMFT
- **Getting Started**: Installation guides and quick start
- **Core Concepts**: Detailed information about transfers, connections, and schedules
- **Advanced Features**: Webhooks, email notifications, and admin tools
- **Security**: Security best practices and configuration
- **Development**: Project structure and contributing guidelines
## Contributing
Contributions to the documentation are welcome! Please submit a PR with your changes.
## Community
Join our [Discord community](https://discord.gg/f9dwtM3j) for support, discussions, and updates about GoMFT.
## License
This documentation is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+183
View File
@@ -0,0 +1,183 @@
---
sidebar_position: 3
title: Admin Tools
---
# Admin Tools
GoMFT provides a comprehensive set of administrative tools for system management, monitoring, and maintenance. These tools help administrators maintain the system, troubleshoot issues, and ensure optimal performance.
## Accessing Admin Tools
Admin tools are available to users with administrator privileges:
1. Log in with an administrator account
2. Navigate to **Admin Tools** in the sidebar menu
## Log Viewer
The Admin Tools panel includes an integrated log viewer with the following features:
### Features
- **Log File Browser**: View a list of all available log files in the system
- **Real-time Log Viewing**: View log file contents directly in the web interface
- **Refresh Function**: Update the log list and content with the latest information
- **User-friendly Interface**: Clean, readable presentation with custom scrolling
- **Dark Mode Support**: Consistent theming with the rest of the application
- **Navigation**: Easily switch between different log files
### Available Logs
- **Application Logs**: General application logs
- **Transfer Logs**: Detailed logs of file transfer operations
- **Authentication Logs**: Login attempts and authentication events
- **Scheduler Logs**: Information about scheduled job execution
- **API Logs**: API usage and requests
- **Webhook Logs**: Records of webhook delivery attempts
- **Email Logs**: Email sending attempts and errors
### Using the Log Viewer
1. Select a log category from the dropdown menu
2. Choose a specific log file from the list
3. View the log content in the main panel
4. Use the search function to find specific text
5. Click **Refresh** to update with the latest entries
## Database Management
The Admin Tools interface also includes database management capabilities:
### Backup Management
- **Create Backup**: Generate a backup of the GoMFT database
- **Schedule Backups**: Configure automatic backup schedules
- **View Backups**: List all available backups with their dates and sizes
- **Download Backup**: Download a backup file for safekeeping
- **Restore Backup**: Restore the system from a previous backup
### Database Operations
- **Optimize Database**: Run maintenance tasks to optimize performance
- **Check Integrity**: Verify database integrity and identify issues
- **Vacuum Database**: Reclaim unused space in the database
- **View Statistics**: Get database size and table statistics
## System Information
The System Information panel provides a comprehensive overview of your GoMFT installation:
### System Stats
- **Version Information**: Current GoMFT version and build details
- **System Resources**: CPU, memory, and disk usage
- **Uptime**: System uptime and start time
- **Active Transfers**: Currently running transfers
- **Queued Transfers**: Transfers waiting to be executed
- **Database Size**: Current size of the database
### Health Checks
- **Service Status**: Status of all system services
- **Storage Space**: Available space in data directories
- **Connection Tests**: Tests for external services like SMTP
- **Rclone Status**: Verify rclone availability and version
## User Management
Administrators can manage user accounts and permissions:
### User Operations
- **Create User**: Add new users to the system
- **Edit User**: Modify existing user details and permissions
- **Deactivate User**: Temporarily disable user accounts
- **Delete User**: Permanently remove a user account
- **Reset Password**: Force password reset for a user
### Role Management
- **View Roles**: List all available roles and their permissions
- **Create Role**: Define custom roles with specific permissions
- **Edit Role**: Modify permissions for existing roles
- **Assign Roles**: Change role assignments for users
## System Settings
The System Settings section allows customization of various system parameters:
### General Settings
- **System Name**: Customize the application name
- **Base URL**: Set the base URL for the application
- **Time Zone**: Configure the system time zone
- **Date Format**: Set the preferred date and time format
- **Default Language**: Set the default interface language
### Security Settings
- **Password Policy**: Configure password complexity requirements
- **Session Timeout**: Set the inactive session timeout period
- **Failed Login Limit**: Set thresholds for account lockouts
- **API Token Management**: Configure API token policies
### Email Settings
- **SMTP Configuration**: Set up the mail server for notifications
- **Email Templates**: Customize notification email templates
- **Notification Rules**: Configure default notification settings
### Transfer Settings
- **Concurrency Limits**: Set maximum simultaneous transfers
- **Bandwidth Limits**: Configure default bandwidth limitations
- **Temporary Storage**: Configure temp directory for transfers
- **Transfer Timeouts**: Set default timeouts for transfers
## Maintenance Mode
Administrators can put the system into maintenance mode when needed:
<!-- ### Maintenance Options
- **Enable Maintenance Mode**: Temporarily restrict access to admin users
- **Scheduled Maintenance**: Schedule maintenance windows
- **Maintenance Message**: Customize the message shown to users
- **Allow Specific IPs**: Allow specific IP addresses during maintenance -->
## Import/Export
The system provides facilities for importing and exporting configuration:
### Import/Export Features
- **Export Configurations**: Export transfer configurations as JSON
- **Import Configurations**: Import configurations from JSON files
- **Migrate Settings**: Move settings between GoMFT instances
- **Bulk Operations**: Perform operations on multiple items
## Audit Logs
For security and compliance, GoMFT maintains comprehensive audit logs:
### Audit Log Features
- **User Actions**: Records of all user-initiated actions
- **System Events**: Important system-level events
- **Authentication Events**: Login, logout, and access attempts
- **Configuration Changes**: Changes to system configuration
- **Filtering**: Filter logs by user, action type, and date range
- **Export**: Export audit logs for compliance reporting
<!-- ## Troubleshooting Tools
The Admin Tools includes several utilities for troubleshooting:
### Troubleshooting Features
- **Test Connections**: Verify connectivity to remote systems
- **Check File Permissions**: Test access to file systems
- **Debug Mode**: Enable additional logging for troubleshooting
- **Transfer Simulation**: Test transfers without moving data
- **System Check**: Run a comprehensive system check -->
+102
View File
@@ -0,0 +1,102 @@
---
sidebar_position: 3
title: Gotify Notifications
---
# Gotify Notifications
Gotify is a simple server for sending and receiving push notifications. GoMFT integrates with Gotify to provide real-time notifications for transfer events and system alerts.
## Overview
Gotify integration allows GoMFT to:
- Send push notifications to your self-hosted Gotify server
- Customize notification priority based on event importance
- Include detailed transfer information in notifications
- Support private and secure notification delivery
## Prerequisites
Before setting up Gotify notifications in GoMFT, you need:
1. A running Gotify server (self-hosted)
2. An application token from your Gotify server
3. Network connectivity between GoMFT and the Gotify server
## Configuration
### Global Gotify Settings
To configure Gotify notifications:
1. Navigate to **Settings** > **Notification Services** > **Add New** > **Gotify**
2. Configure the following settings:
- **Gotify Server URL**: The URL of your Gotify server (e.g., `https://gotify.example.com`)
- **Application Token**: The token for your GoMFT application in Gotify
- **Default Priority**: The default priority level for notifications (1-10)
- **Verify SSL**: Whether to verify SSL certificates (recommended for production)
### Testing Gotify Connection
After configuring your Gotify settings:
1. Click **Test Connection** to verify connectivity with your Gotify server
2. Click **Send Test Notification** to send a test message
## Notification Content
### Priority Levels
Gotify uses numeric priority levels that GoMFT leverages for different event types:
| Priority | Usage in GoMFT |
|----------|----------------|
| 1-3 | Low priority: successful transfers, routine events |
| 4-7 | Medium priority: warnings, transfers with issues |
| 8-10 | High priority: failed transfers, critical system issues |
### Example Notifications
GoMFT sends structured notifications with helpful information:
#### Successful Transfer
```
Title: Transfer Completed: Daily Backup
Message: Successfully transferred 123 files (1.45 GB) in 2:15
Priority: 3
```
#### Failed Transfer
```
Title: Transfer Failed: Daily Backup
Message: Error: Connection refused to destination server
Files processed: 45/123
Size transferred: 0.5/1.45 GB
Priority: 8
```
## Troubleshooting
### Common Issues
- **Connection Refused**: Ensure the Gotify server URL is correct and accessible
- **Authentication Failed**: Verify the Application Token is correct
- **SSL Certificate Errors**: Check the Verify SSL setting and certificate validity
### Gotify Logs
To troubleshoot notification issues:
1. Check the GoMFT logs: **Admin Tools** > **Logs** > filter for "gotify"
2. Review the Gotify server logs for any errors
3. Verify network connectivity between GoMFT and the Gotify server
## Best Practices
- **Use HTTPS** for your Gotify server to ensure secure communication
- **Set Appropriate Priorities** to differentiate between routine and critical notifications
- **Use Client Applications** on your devices to receive Gotify notifications
- **Set Up Multiple Notification Methods** for critical events
@@ -0,0 +1,128 @@
---
sidebar_position: 1
title: Notifications Overview
---
# Notifications Overview
GoMFT provides a comprehensive notification system to keep you informed about important events in your file transfer workflows. This page provides an overview of the notification system and the different notification types available.
## Notification System
The notification system in GoMFT is designed to be:
- **Flexible**: Choose from multiple notification channels
- **Configurable**: Set up different notifications for different events
- **Reliable**: Ensure critical events are always reported
- **Secure**: Protect sensitive information in notifications
## Notification Triggers
Notifications can be triggered by various events in GoMFT:
### Transfer-Related Events
- **Transfer Completion**: When a file transfer is successfully completed
- **Transfer Failure**: When a file transfer fails for any reason
- **Transfer Start**: When a file transfer begins
- **Transfer Threshold**: When a transfer exceeds a defined duration threshold
### Schedule-Related Events
- **Schedule Execution**: When a scheduled task runs
- **Schedule Failure**: When a scheduled task fails to run
- **Schedule Creation/Modification**: When schedules are created or modified
<!-- ### System Events
- **System Warnings**: Alerts about system resource usage (disk space, memory, etc.)
- **Service Status Changes**: When system services change state
- **Authentication Events**: Failed login attempts or other security events
- **Database Events**: Database backup completion, migration, or issues -->
## Notification Types
GoMFT supports multiple notification types to ensure you can receive alerts through your preferred channels:
### Webhook Notifications
Send HTTP requests to external systems or services when events occur. Features include:
- Configurable HTTP methods (POST, PUT, PATCH)
- JSON or XML payload formats
- Support for authentication
- Customizable retry strategy for improved reliability
[Learn more about Webhook Notifications](./webhook-notifications)
### Mobile Push Notifications
Receive notifications directly on your mobile devices:
#### Ntfy Notifications
- Simple HTTP-based push notifications to phones and desktops
- Customizable priority levels and notification tags
- Support for self-hosted or cloud-based ntfy servers
[Learn more about Ntfy Notifications](./ntfy-notifications)
#### Pushover Notifications
- Real-time push notifications to all your devices
- Priority levels for urgent notifications
- Custom sounds and delivery options
[Learn more about Pushover Notifications](./pushover-notifications)
#### Pushbullet Notifications
- Cross-platform notifications across all your devices
- Optional end-to-end encryption
- Support for notification mirroring
[Learn more about Pushbullet Notifications](./pushbullet-notifications)
#### Gotify Notifications
- Self-hosted push notification service
- Customizable priority levels
- Private and secure notification delivery
[Learn more about Gotify Notifications](./gotify-notifications)
## Notification Templates
Each notification type uses customizable templates to format the notification content. Templates support variables that are replaced with actual values when the notification is sent.
Common template variables include:
- `{{transfer_name}}`: Name of the transfer
- `{{transfer_status}}`: Status of the transfer (success, failure, etc.)
- `{{start_time}}`: When the transfer started
- `{{end_time}}`: When the transfer completed
- `{{duration}}`: How long the transfer took
- `{{total_files}}`: Number of files transferred
- `{{total_size}}`: Total size of transferred data
- `{{error_message}}`: Detailed error information (for failures)
## Notification Management
### Configuration
Notifications are configured at multiple levels:
1. **Global Level**: Default notification settings for all transfers
2. **Transfer Level**: Specific notification settings for individual transfers
3. **Schedule Level**: Notification settings for scheduled transfers
### Notification History
GoMFT maintains a history of sent notifications, allowing you to:
- Review past notifications
- Verify notification delivery
- Resend notifications if needed
- Audit notification patterns
## Getting Started with Notifications
To start using GoMFT notifications:
1. Navigate to **Settings** > **Notifications**
2. Configure your preferred notification channels
3. Test each notification channel
4. Apply notifications to specific transfers or schedules
For specific notification types, refer to the corresponding documentation pages in this section.
+155
View File
@@ -0,0 +1,155 @@
---
sidebar_position: 4
title: Ntfy Notifications
---
# Ntfy Notifications
Ntfy is a simple HTTP-based pub-sub notification service that allows you to send push notifications to your phone or desktop. GoMFT seamlessly integrates with Ntfy to deliver notifications about your file transfers and system events.
## Overview
Ntfy integration in GoMFT enables:
- Push notifications to mobile devices and desktops
- Choice between public ntfy.sh service or self-hosted Ntfy server
- Customizable notification topics, priorities, and tags
- Support for notification actions and attachments
## Prerequisites
Before configuring Ntfy notifications in GoMFT, you should:
1. Install the Ntfy app on your devices (available for Android, iOS, and desktop)
2. Subscribe to your chosen topic in the Ntfy app
3. Optionally set up your own Ntfy server for increased privacy
## Configuration
### Global Ntfy Settings
To configure Ntfy notifications in GoMFT:
1. Navigate to **Settings** > **Notification Services** > **Add New** > **Ntfy**
2. Configure the following settings:
- **Ntfy Server URL**: The URL of the Ntfy server (default: `https://ntfy.sh`)
- **Default Topic**: The notification topic your devices are subscribed to
- **Default Priority**: Priority level for notifications (1-5)
- **Authentication**: Access token or username/password if required
- **Default Tags**: Icon tags for different notification types
### Testing Ntfy Connection
After configuring your Ntfy settings:
1. Click **Send Test Notification** to send a test notification to your devices
## Notification Content
### Priority Levels
Ntfy supports five priority levels that GoMFT uses effectively:
| Priority | Level | Usage in GoMFT |
|----------|-------|----------------|
| 1 | Min | Background information, debug notifications |
| 2 | Low | Successful transfers, routine events |
| 3 | Default | Standard notifications, warnings |
| 4 | High | Transfer failures, important alerts |
| 5 | Max | Critical system issues, emergency alerts |
### Notification Tags
GoMFT uses meaningful tags in Ntfy notifications to provide visual cues:
| Tag | Usage |
|-----|-------|
| `✅` | Successful transfers |
| `❌` | Failed transfers |
| `⚠️` | Warnings or transfers with issues |
| `🔄` | Transfer in progress |
| `🔍` | Monitoring events |
| `⚙️` | System events |
### Example Notifications
GoMFT sends structured notifications with helpful information:
#### Successful Transfer
```
Title: Transfer Completed: Daily Backup
Message: Successfully transferred 123 files (1.45 GB) in 2:15
Priority: 2 (Low)
Tags: ✅,📁
```
#### Failed Transfer
```
Title: Transfer Failed: Daily Backup
Message: Error: Connection refused to destination server
Files processed: 45/123
Size transferred: 0.5/1.45 GB
Priority: 4 (High)
Tags: ❌,📁
Click action: Open GoMFT
```
## Advanced Features
### Custom Templates
Customize notification content with templates:
```
Title: {{event_type}}: {{transfer_name}}
Message: {{status}} - {{files_transferred}} files ({{total_size}}) in {{duration}}
Priority: {% if status == "failed" %}4{% else %}2{% endif %}
Tags: {% if status == "success" %}✅{% else %}❌{% endif %},📁
```
## Self-Hosting Ntfy
For enhanced privacy and control, you can self-host your own Ntfy server:
1. Follow the [Ntfy self-hosting guide](https://docs.ntfy.sh/install/)
2. Update your GoMFT configuration to point to your self-hosted server
3. Configure authentication as needed
Example configuration for self-hosted Ntfy:
```yaml
ntfy:
server_url: https://ntfy.example.com
default_topic: gomft
authentication:
type: basic
username: ${NTFY_USERNAME}
password: ${NTFY_PASSWORD}
```
## Troubleshooting
### Common Issues
- **Notifications Not Arriving**: Verify you've subscribed to the correct topic
- **Authentication Errors**: Check credentials and authentication method
- **Connection Issues**: Ensure the Ntfy server is accessible from GoMFT
- **App Configuration**: Verify notification settings in your Ntfy app
### Ntfy Logs
To troubleshoot notification issues:
1. Check the GoMFT logs: **Administration** > **Log Viewer** > filter for "ntfy"
2. If self-hosting, check your Ntfy server logs
3. Verify your device has properly functioning notifications
## Best Practices
- **Use Unique Topics** to prevent unauthorized notifications
- **Set Appropriate Priorities** based on event importance
- **Consider Self-Hosting** for sensitive environments
- **Keep Topic Names Secret** as they act like passwords
- **Set Up Multiple Notification Methods** for critical systems
@@ -0,0 +1,131 @@
---
sidebar_position: 5
title: Pushbullet Notifications
---
# Pushbullet Notifications
Pushbullet is a cross-platform notification service that allows you to receive notifications on multiple devices. GoMFT integrates with Pushbullet to deliver timely notifications about your file transfers and system events.
## Overview
Pushbullet integration in GoMFT offers:
- Cross-platform notifications across your devices (Android, iOS, Chrome, Firefox, etc.)
- Option to send to all devices or specific devices
- Rich notification content with transfer details
- Support for notification mirroring between devices
## Prerequisites
Before configuring Pushbullet notifications in GoMFT, you need:
1. A Pushbullet account
2. Pushbullet API access token
3. Pushbullet app installed on your devices
## Configuration
### Global Pushbullet Settings
To configure Pushbullet notifications:
1. Navigate to **Settings** > **Notification Services** > **Add New** > **Pushbullet**
2. Configure the following settings:
- **API Token**: Your Pushbullet access token
- **Default Device**: The device identifier to send notifications to (optional)
- **Default Type**: "Note" (default) or "Link"
### Getting Your Pushbullet API Token
1. Log in to your Pushbullet account at [pushbullet.com](https://www.pushbullet.com/)
2. Go to **Settings** > **Account**
3. In the **Access Tokens** section, click **Create Access Token**
4. Copy the generated token and paste it into GoMFT
### Testing Pushbullet Connection
After configuring your Pushbullet settings:
1. Click **Send Test Notification** to send a test notification to your devices
## Notification Content
### Notification Types
GoMFT supports two types of Pushbullet notifications:
#### Note Type
Simple notifications with a title and body:
```
Title: Transfer Complete: Daily Backup
Body: Successfully transferred 123 files (1.45 GB) in 2:15
```
#### Link Type
Notifications that include a link to the GoMFT interface:
```
Title: Transfer Failed: Daily Backup
Body: Error: Connection refused to destination server
URL: https://gomft.example.com/transfers/123
```
### Example Notifications
#### Successful Transfer
```
Title: Transfer Complete: Daily Backup
Body: Transfer completed successfully at 2023-09-15 14:22:33
Files: 123
Size: 1.45 GB
Duration: 00:02:15
```
#### Failed Transfer
```
Title: Transfer Failed: Daily Backup
Body: Transfer failed with error: Connection refused
Files Processed: 45/123
Size Transferred: 0.5/1.45 GB
Duration: 00:01:05
Error: Failed to connect to destination server
URL: https://gomft.example.com/transfers/123
```
## Troubleshooting
### Common Issues
- **API Token Errors**: Verify your Pushbullet API token is correct
- **No Notifications Arriving**: Check device connectivity and Pushbullet app settings
- **Rate Limiting**: Pushbullet has API rate limits; spread out notification frequency
- **Device Selection Issues**: Verify device identifiers if targeting specific devices
### Pushbullet Logs
To troubleshoot notification issues:
1. Check the GoMFT logs: **Administration** > **Log Viewer** > filter for "pushbullet"
2. Review the Pushbullet account activity in your Pushbullet account
## Best Practices
- **Secure Your API Token**: Treat your Pushbullet API token as sensitive information
- **Group Related Notifications** to avoid notification fatigue
- **Include Action Links** for quick access to relevant GoMFT pages
- **Set Up Multiple Notification Methods** for critical systems
## Pushbullet Alternatives
If you encounter limitations with Pushbullet, GoMFT also supports:
- [Email Notifications](./email-notifications)
- [Gotify](./gotify-notifications)
- [Ntfy](./ntfy-notifications)
- [Pushover](./pushover-notifications)
@@ -0,0 +1,137 @@
---
sidebar_position: 6
title: Pushover Notifications
---
# Pushover Notifications
Pushover is a simple notification service that makes it easy to send real-time notifications to your Android and iOS devices, as well as desktop computers. GoMFT integrates with Pushover to deliver instant notifications about your file transfers and system events.
## Overview
Pushover integration in GoMFT provides:
- Real-time push notifications to mobile devices and desktops
- Prioritized notifications with different sounds and attention levels
- Customizable notification content with detailed transfer information
- Support for notification grouping by device or application
## Prerequisites
Before configuring Pushover notifications in GoMFT, you need:
1. A [Pushover account](https://pushover.net/)
2. Your Pushover user key
3. A registered Pushover application (API token)
4. Pushover app installed on your devices
## Configuration
### Registering a GoMFT Application in Pushover
1. Log in to your Pushover account at [pushover.net](https://pushover.net/)
2. Go to [Your Applications](https://pushover.net/apps/build)
3. Create a new application:
- **Name**: GoMFT
- **Type**: Application
- **Description**: GoMFT File Transfer Notifications
- **URL**: Your GoMFT instance URL (optional)
- **Icon**: Upload a custom icon (optional)
4. After creation, you'll receive an **API Token/Key** for your application
### Global Pushover Settings
To configure Pushover notifications in GoMFT:
1. Navigate to **Settings** > **Notification Services** > **Add New** > **Pushover**
2. Configure the following settings:
- **User Key**: Your Pushover user key
- **API Token**: Your GoMFT application's API token
- **Default Priority**: Default priority level (-2 to 2)
- **Default Sound**: Sound for notifications
- **Default Device**: Specific device or blank for all devices
### Testing Pushover Connection
After configuring your Pushover settings:
1. Click **Send Test Notification** to send a test notification to your devices
## Notification Content
### Priority Levels
Pushover supports different priority levels that GoMFT uses effectively:
| Priority | Level | Usage in GoMFT |
|----------|-------|----------------|
| -2 | Lowest | Silent transfer logs, debugging info |
| -1 | Low | Successful transfers, routine events |
| 0 | Normal | Standard notifications |
| 1 | High | Transfer failures, important alerts |
| 2 | Emergency | Critical system issues |
Note: Emergency priority (2) notifications will repeat until acknowledged by the user.
### Example Notifications
#### Successful Transfer
```
Title: Transfer Complete: Daily Backup
Message: Successfully transferred 123 files (1.45 GB) in 2:15
Priority: Normal (0)
Sound: pushover
```
#### Failed Transfer
```
Title: Transfer Failed: Daily Backup
Message: Error: Connection refused to destination server
Files: 45/123 processed
Size: 0.5/1.45 GB transferred
Error: Failed to connect to destination server
Priority: High (1)
Sound: siren
URL: https://gomft.example.com/transfers/123
URL Title: View Transfer Details
```
## Troubleshooting
### Common Issues
- **Incorrect API Token/User Key**: Verify your Pushover credentials
- **Message Rate Limiting**: Pushover has monthly message limits for free accounts
- **Device Not Receiving**: Check device registration and network connectivity
- **Emergency Notifications**: Verify retry/expire settings for emergency priority
### Pushover Logs
To troubleshoot notification issues:
1. Check the GoMFT logs: **Admin Tools** > **Logs** > filter for "pushover"
2. Review your Pushover account's message history
3. Check your device's Pushover app settings
## Best Practices
- **Use Appropriate Priority Levels** based on event importance
- **Reserve Emergency Priority** for truly critical issues
- **Group Related Notifications** when possible
- **Include Action URLs** for immediate access to relevant information
- **Consider Sound Selection** based on notification importance
- **Set Up Multiple Notification Methods** for critical systems
## Pushover vs. Other Notification Systems
| Feature | Pushover | Email | Gotify | Ntfy | Pushbullet |
|---------|----------|-------|--------|------|------------|
| Cost | Paid (one-time) | Free | Free | Free | Free/Paid |
| Self-hosting | No | Varies | Yes | Yes | No |
| Priority levels | Yes | No | Yes | Yes | No |
| Acknowledgment | Yes | No | No | No | No |
| Sound options | Yes | No | No | Limited | No |
| Delivery guarantee | High | Varies | Good | Good | Good |
| Device support | iOS, Android, Desktop | All | All | All | iOS, Android, Desktop |
+147
View File
@@ -0,0 +1,147 @@
---
sidebar_position: 3
title: Webhook Notifications
---
# Webhook Notifications
Webhook notifications in GoMFT provide a powerful way to integrate with external systems by sending HTTP requests when events occur. This enables automation workflows and integration with your existing tools and services.
## Overview
Webhooks allow GoMFT to:
- Send real-time notifications to external systems
- Trigger automated workflows in third-party applications
- Integrate with custom applications or services
- Provide machine-readable event data (JSON or XML)
## Configuration
### Global Webhook Settings
To configure webhook notifications:
1. Navigate to **Settings** > **Notification Services** > **Webhooks**
2. Configure the following settings:
- **Default Webhook URL**: The base URL for webhook requests
- **HTTP Method**: POST (default), PUT, or PATCH
- **Content Type**: application/json (default), application/xml, or custom
- **Authentication**: None, Basic Auth, API Key, or Bearer Token
- **Retry Strategy**: Number of retries and delay between retries
- **Timeout**: Maximum wait time for responses
### Testing Webhook Connectivity
After configuring your webhook settings:
1. Click **Test Connection** to send a test webhook request
2. Review the response status and body from the server
## Webhook Payload
### Default JSON Payload
By default, GoMFT sends a JSON payload with information about the event:
```json
{
"event_type": "transfer_completed",
"timestamp": "2023-09-15T14:22:33Z",
"transfer": {
"id": "transfer-123",
"name": "Daily Backup",
"source": "local-server",
"destination": "cloud-storage",
"status": "success",
"start_time": "2023-09-15T14:20:01Z",
"end_time": "2023-09-15T14:22:33Z",
"duration_seconds": 152,
"files_transferred": 258,
"total_size_bytes": 1073741824,
"transfer_rate_bytes_per_second": 7064091
},
"schedule": {
"id": "schedule-456",
"name": "Daily Backup Schedule"
}
}
```
For failure events, additional error information is included:
```json
{
"event_type": "transfer_failed",
"timestamp": "2023-09-15T14:22:33Z",
"transfer": {
"id": "transfer-123",
"name": "Daily Backup",
"source": "local-server",
"destination": "cloud-storage",
"status": "failed",
"start_time": "2023-09-15T14:20:01Z",
"end_time": "2023-09-15T14:22:33Z",
"duration_seconds": 152,
"error": {
"code": "CONNECTION_ERROR",
"message": "Failed to connect to destination: Connection timed out",
"details": "TCP connection to cloud-storage:22 timed out after 60 seconds"
}
}
}
```
### Custom Payload Templates
You can customize the webhook payload using templates:
1. Navigate to the webhook configuration
2. Switch from **Default Payload** to **Custom Payload**
3. Edit the JSON or XML template
Example custom template:
```json
{
"alert": {
"type": "{{event_type}}",
"system": "GoMFT",
"environment": "{{environment}}",
"details": {
"transfer_name": "{{transfer_name}}",
"status": "{{status}}",
"time": "{{timestamp}}",
"size_mb": "{{total_size_mb}}"
}{% if status == "failed" %},
"error": "{{error_message}}"{% endif %}
}
}
```
## Troubleshooting
### Common Issues
- **Connection Refused**: Check network connectivity and firewall rules
- **Authentication Failed**: Verify credentials and authentication method
- **Timeout Issues**: Increase timeout settings for slow endpoints
- **Invalid Payload**: Validate your custom template syntax
- **HTTP Error Codes**: Check destination service logs for details
### Webhook Logs
GoMFT logs all webhook attempts:
1. Navigate to **Administartion** > **Log Viewer**
2. Filter for "webhook" to see relevant log entries
3. Review request and response details for troubleshooting
## Best Practices
- **Use HTTPS** for all webhook endpoints
- **Implement Retries** for important notifications
- **Monitor Webhook Deliveries** to ensure reliability
- **Set Up Fallback Notification Methods** for critical transfers
- **Validate Webhook Payloads** on the receiving end
- **Keep Webhook Processing Fast** to avoid timeouts
+128
View File
@@ -0,0 +1,128 @@
---
sidebar_position: 2
title: Connections
---
# Connection Management
Connections in GoMFT are configurations that define how to access different storage systems. Before you can transfer files, you need to set up connections for your source and destination systems.
## Supported Connection Types
GoMFT leverages rclone as its transfer engine, supporting a wide range of storage systems:
### Cloud Storage
- **Amazon S3**: Amazon's object storage service
- **Google Cloud Storage**: Google's object storage service
- **Backblaze B2**: Affordable cloud object storage
- **Wasabi**: Hot cloud storage
### File Transfer Protocols
- **FTP**: File Transfer Protocol
- **SFTP**: SSH File Transfer Protocol
- **WebDAV**: Web Distributed Authoring and Versioning
### Local Storage
- **Local Disk**: Files on the server running GoMFT
- **SMB/CIFS**: Windows file sharing
## Creating a Connection
To create a new connection:
1. Navigate to the **Transfer Configuration** section in the sidebar
2. Click **+ New Configuration**
3. Select the connection type from the dropdown menu
4. Fill in the required details for your selected type
5. Click **Test Source/Destination** to verify the connection works
6. Click **Create Configuration** to store the configuration
## Connection Configuration Fields
Different connection types require different configuration fields. Here are some common examples:
### Amazon S3 Connection
- **Name**: A descriptive name for the connection
- **Access Key ID**: AWS access key
- **Secret Access Key**: AWS secret key
- **Region**: AWS region (e.g., us-east-1)
- **Endpoint**: Optional custom endpoint for S3-compatible services
- **Bucket**: Default bucket to use (optional)
- **Path Prefix**: Default path prefix within the bucket (optional)
### SFTP Connection
- **Name**: A descriptive name for the connection
- **Host**: Server hostname or IP address
- **Port**: Server port (usually 22)
- **Username**: SFTP username
- **Authentication Method**: Password or SSH Key
- **Password**: User password (if using password authentication)
- **SSH Key**: Private SSH key (if using key authentication)
- **SSH Key Passphrase**: Passphrase for SSH key (if applicable)
### Local Storage Connection
- **Name**: A descriptive name for the connection
- **Path**: Base path on the local filesystem
## Connection Security
GoMFT follows best practices for handling connection credentials:
- **Encryption**: All sensitive credentials are encrypted at rest
- **Access Control**: Connections are protected by user permissions
- **Masked Values**: Passwords and secret keys are masked in the UI
- **Key Management**: SSH keys and other credentials are securely stored
## Managing Connections
### Viewing Connections
The **Transfer Configurations** page displays all configured connections with:
- Configuration name
- Configuration type
- Last updated date
### Editing Transfer Confirgurations
To edit an existing connection:
1. Navigate to the **Transfer Confiruations** section
2. Find the config you want to edit
3. Click the **Edit** button
4. Modify the config details
5. Test the updated configuration
6. Save your changes
### Deleting Transfer Configurations
To delete a connection:
1. Navigate to the **Transfer Configurations** section
2. Find the config you want to delete
3. Click the **Delete** button
4. Confirm the deletion
**Note**: You cannot delete connections that are in use by active transfers or schedules.
## Testing Transfer Configurations
GoMFT includes a configuration testing feature to verify connectivity:
1. After entering details for a configuration, click **Test Source/Destination**
2. GoMFT will attempt to authenticate with the remote system
3. For file storage, it will also verify read/write permissions
4. Results will display showing success or failure details
## Best Practices
- **Use descriptive names** for connections to easily identify them
- **Test connections regularly** to ensure they still work
- **Rotate credentials** periodically for enhanced security
- **Use service accounts** rather than personal accounts when possible
- **Document connection details** in the description field
- **Use the minimal required permissions** for enhanced security
- **Organize connections** using consistent naming conventions
+112
View File
@@ -0,0 +1,112 @@
---
sidebar_position: 4
title: Monitoring
---
# Monitoring and Reporting
GoMFT provides comprehensive monitoring and reporting features to help you track transfer activities, analyze performance, and ensure reliable operation. This page explains the monitoring tools available in GoMFT.
## Dashboard
The GoMFT dashboard provides a real-time overview of your file transfer system:
### Dashboard Components
- **Transfer Status**: Overview of currently running, completed, and failed transfers
- **Recent Transfers**: List of the most recent transfer executions
- **System Health**: Indicators for system health and resource usage
- **Quick Actions**: Buttons for common tasks like creating transfers or checking logs
To access the dashboard:
1. Log in to GoMFT
2. The dashboard is the default landing page
3. You can return to it anytime by clicking **Dashboard** in the sidebar
## Transfer History
The transfer history section provides detailed information about all transfer executions:
### Transfer History Features
- **Comprehensive Logs**: Complete transfer history with filtering options
- **Status Tracking**: Visual indicators for transfer status (successful, failed, in progress)
- **Performance Metrics**: Data on transfer speed, file counts, and total bytes
- **Time Tracking**: Start time, end time, and duration for all transfers
- **Filter and Search**: Find specific transfers by name, status, date, or other criteria
To access transfer history:
1. Navigate to **Transfer History** in the sidebar
2. Use filters to narrow down the list of transfers
3. Click on any transfer to see detailed information
## Real-Time Monitoring
GoMFT provides real-time monitoring of active transfers:
### Active Transfers
- **Live Progress**: See transfer progress as it happens
- **File Counters**: Track files transferred, remaining, and skipped
- **Bandwidth Usage**: Monitor current transfer speeds
- **Cancel Option**: Ability to cancel running transfers
- **Log Streaming**: View logs as they're generated
To monitor active transfers:
1. Navigate to **Transfer History** in the sidebar
2. View all currently running transfers
3. Click on any transfer to see detailed progress
## Detailed Transfer Logs
For each transfer execution, GoMFT maintains detailed logs:
### Log Information
- **File Details**: Information about each transferred file
- **Error Messages**: Detailed error information for failed transfers
- **Warning Messages**: Warnings that occurred during transfer
- **Transfer Summary**: Overall summary of the transfer operation
- **Performance Data**: Transfer rates and timing information
To access detailed logs:
1. Navigate to **Transfer History** in the sidebar
2. Find the transfer of interest
3. Click on **View Details** to open details
## System Monitoring
GoMFT monitors the health and performance of the system itself:
## Alerts and Notifications
GoMFT can alert you to important events:
### Alert Types
- **Transfer Failures**: Notifications when transfers fail
- **Transfer Completion**: Alerts when transfers complete
To configure alerts:
1. Navigate to **Notification Providers**
2. Set up notification methods (email, webhook, gotify, ntfy, pushover, pushbullet)
4. Configure alert severity levels
## Export and API Access
GoMFT allows you to export monitoring data:
### Export Options
- **CSV Export**: Download transfer history in CSV format
- **JSON Export**: Export data in JSON format for further processing
## Best Practices
- **Review the dashboard daily** to stay informed of transfer status
- **Set up alerts** for critical transfers to be notified of failures
- **Generate regular reports** for compliance and performance tracking
- **Monitor system health** to prevent resource issues
- **Archive logs** for long-term storage and compliance
- **Use filters** to focus on the most important information
- **Export data** for backup and external analysis
+192
View File
@@ -0,0 +1,192 @@
---
sidebar_position: 3
title: Schedules
---
# Schedule Management
GoMFT's scheduling system allows you to automate file transfers to run at specific times or on a recurring basis. This section explains how to create, manage, and monitor scheduled transfers.
## Schedule Types
GoMFT supports several types of schedules:
### One-Time Schedules
Run a transfer once at a specific date and time.
### Recurring Schedules
Run a transfer repeatedly according to a defined pattern:
- **Hourly**: Run every hour at a specific minute
- **Daily**: Run every day at a specific time
- **Weekly**: Run on specific days of the week
- **Monthly**: Run on specific days of the month
- **Custom**: Define a custom schedule using cron syntax
## Creating a Schedule
To create a new schedule:
1. Navigate to the **Schedules** section in the sidebar
2. Click **Create New Schedule**
3. Select the transfer to schedule
4. Choose the schedule type
5. Configure the schedule details
6. Set additional options
7. Click **Save Schedule**
## Schedule Configuration
### Basic Configuration
- **Name**: A descriptive name for the schedule
- **Transfer**: The transfer configuration to run
- **Enabled**: Toggle to enable or disable the schedule
- **Schedule Type**: One-time or recurring
### One-Time Schedule Options
- **Date**: The date to run the transfer
- **Time**: The time to run the transfer
### Recurring Schedule Options
#### Simple Options
- **Frequency**: Hourly, Daily, Weekly, Monthly, or Custom
- **Time**: The time to run (for Daily, Weekly, Monthly)
- **Days**: The days to run (for Weekly, Monthly)
- **Minutes**: The minute to run (for Hourly)
#### Advanced Options (Cron Syntax)
For more complex scheduling needs, you can use cron syntax:
```
┌─────────── minute (0 - 59)
│ ┌──────── hour (0 - 23)
│ │ ┌────── day of month (1 - 31)
│ │ │ ┌──── month (1 - 12)
│ │ │ │ ┌── day of week (0 - 6) (Sunday to Saturday)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
* * * * *
```
Examples:
- `0 2 * * *`: Every day at 2:00 AM
- `0 9-17 * * 1-5`: Every hour from 9 AM to 5 PM, Monday to Friday
- `*/15 * * * *`: Every 15 minutes
- `0 0 1,15 * *`: 1st and 15th of every month at midnight
### Additional Options
- **Timeout**: Maximum duration for the transfer (after which it will be terminated)
- **Retry Count**: Number of times to retry on failure
- **Retry Delay**: Time to wait between retry attempts
- **Priority**: Schedule priority (higher priority schedules run first when multiple are due)
- **Description**: Additional notes about the schedule
## Schedule Groups
GoMFT allows you to organize schedules into logical groups:
1. Navigate to **Schedule Groups** in the Schedules section
2. Create a new group with a name and description
3. Assign schedules to the group
4. View and manage grouped schedules together
Benefits of groups:
- Organize related schedules
- Apply batch operations to multiple schedules
- Monitor group-level statistics
## Managing Schedules
### Viewing Schedules
The **Schedules** page displays all configured schedules with:
- Schedule name
- Associated transfer
- Next run time
- Last run status
- Enabled/disabled status
### Editing Scheduled Jobs
To edit an existing schedule:
1. Navigate to the **Scheduled Jobs** section
2. Find the schedule you want to edit
3. Click the **Edit** button
4. Modify the schedule details
5. Save your changes
### Enabling/Disabling Scheduled Jobs
To temporarily disable a schedule without deleting it:
1. Navigate to the **Scheduled Job** section
2. Find the schedule you want to disable
3. Click edit
3. Toggle the **Enabled** switch to Off and save
4. The schedule will remain configured but won't run until re-enabled
### Deleting Schedules
To delete a schedule:
1. Navigate to the **Scheduled Job** section
2. Find the schedule you want to delete
3. Click the **Delete** button
4. Confirm the deletion
## Schedule Execution
When a schedule runs, GoMFT performs these actions:
1. Identifies schedules due for execution
2. Prioritizes schedules based on priority setting
3. Creates execution jobs for the associated transfers
4. Monitors job execution
5. Records results in the history
6. Handles retries if configured and needed
7. Updates next run time for recurring schedules
## Monitoring Schedules
GoMFT provides several ways to monitor your scheduled transfers:
<!-- ### Schedule Calendar
View all scheduled transfers in a calendar view:
1. Navigate to **Schedule Calendar** in the Schedules section
2. See all upcoming scheduled transfers in a monthly, weekly, or daily view
3. Click on any scheduled transfer to see details or edit it -->
### Transfer History
View the execution history of your schedules:
1. Navigate to **Transfer History** on the sidebar
2. See when schedules ran, their status, and execution details
3. Filter by date range, status, or schedule name
## Schedule Notifications
Configure notifications for scheduled transfers:
1. Edit a schedule
2. Navigate to the **Notifications** tab
3. Configure email notifications or webhooks
4. Specify notification conditions (success, failure, or both)
## Best Practices
- **Use descriptive names** for schedules to easily identify them
- **Set appropriate timeouts** based on expected transfer duration
- **Configure retries** for critical transfers
- **Use schedule groups** to organize related schedules
- **Stagger schedules** to avoid resource contention
- **Set up notifications** for critical schedules
- **Review schedule history** regularly to identify issues
- **Disable schedules** instead of deleting them for temporary pauses
+167
View File
@@ -0,0 +1,167 @@
---
sidebar_position: 1
title: Transfers
---
# Transfer Operations
GoMFT's primary function is to manage file transfers between different storage systems. This page explains the transfer operations available in GoMFT and how to configure them.
## Transfer Types
GoMFT supports several types of transfer operations, each with different behaviors:
### Copy
The **Copy** operation copies files from the source to the destination. Files are only copied if they don't exist at the destination or if they've been modified at the source.
```
Source → Destination
```
### Sync
The **Sync** operation makes the destination identical to the source, adding, removing, and updating files as necessary.
```
Source → Destination (with deletions)
```
### Move
The **Move** operation copies files from the source to the destination and then deletes the source files after a successful transfer.
```
Source → Destination → Delete Source
```
### Bidirectional Sync
The **Bidirectional Sync** operation synchronizes files in both directions, ensuring that the newest version of each file is present in both locations.
```
Source ⟷ Destination
```
## Transfer Configuration
When creating a transfer in GoMFT, you need to configure the following elements:
### Basic Configuration
- **Name**: A descriptive name for the transfer
- **Description**: Optional details about the transfer's purpose
- **Source**: The source connection and path
- **Destination**: The destination connection and path
- **Transfer Type**: Copy, Sync, Move, or Bidirectional Sync
### Advanced Options
#### File Selection
- **Include Patterns**: Patterns for files to include (e.g., `*.txt`, `data/**/*.csv`)
- **Exclude Patterns**: Patterns for files to exclude (e.g., `*.tmp`, `**/._*`)
- **Min Size**: Minimum file size to transfer
- **Max Size**: Maximum file size to transfer
- **Min Age**: Only transfer files older than this
- **Max Age**: Only transfer files newer than this
#### Transfer Behavior
- **Checksum**: Compare files using checksums instead of size/date
- **Delete Before**: Delete destination files before transferring
- **Delete During**: Delete destination files during transfer
- **Delete After**: Delete destination files not in source after transfer
- **Update Existing**: Update existing files at destination
- **Skip New**: Skip new files not present at destination
- **Skip Newer**: Skip files that are newer at the destination
#### Performance Options
- **Transfers**: Number of concurrent file transfers
- **Checkers**: Number of concurrent file checkers
- **Bandwidth Limit**: Maximum bandwidth to use in bytes/s
- **Buffer Size**: Size of transfer buffer (default: 16MB)
- **Chunk Size**: Upload chunk size for chunked uploads
## Transfer Execution
### Manual Execution
Transfers can be run on-demand:
1. Navigate to the **Scheduled Jobs** section
2. Find your job in the list
3. Click **Run Now**
4. Monitor the job progress in real-time
### Scheduled Execution
Transfers can be scheduled to run automatically:
1. Navigate to the **Scheduled Jobs** section
2. Create a new schedule linked to your transfer configuration
3. Set up the schedule using cron syntax or the schedule builder
4. The transfer will run automatically according to the schedule
## Transfer Monitoring
### Status Indicators
- **Pending**: Transfer is waiting to start
- **Running**: Transfer is in progress
- **Completed**: Transfer finished successfully
- **Failed**: Transfer encountered an error
- **Canceled**: Transfer was manually canceled
### Transfer Details
For each transfer execution, GoMFT records:
- Start and end times
- Duration
- Number of files transferred
- Total bytes transferred
- Files skipped
- Errors encountered
- Detailed logs
## Transfer Logs
GoMFT provides detailed logs for each transfer:
1. Navigate to **Transfer History**
2. Click on a **View Details** button on the transfer entry
The logs include information about:
- Each file transferred
- Skipped files
- Errors
- Performance metrics
- Overall transfer summary
## Troubleshooting Failed Transfers
When a transfer fails, GoMFT provides information to help identify the cause:
1. Check the error message in the transfer history
2. Review the detailed logs for the specific error
3. Common issues include:
- Permission problems
- Network connectivity
- Invalid credentials
- Path not found
- Disk space issues
## Best Practices
- **Use meaningful names** for your transfers to easily identify them
- **Start small** when testing new configurations
- **Use include/exclude patterns** to limit scope when working with large directories
- **Set appropriate concurrency** based on network conditions and system resources
- **Use checksumming** for critical data to ensure integrity
- **Set bandwidth limits** to avoid network congestion during peak hours
- **Schedule large transfers** during off-peak times
- **Use notifications** to stay informed about transfer results
- **Regularly review logs** to identify potential issues
+221
View File
@@ -0,0 +1,221 @@
---
sidebar_position: 4
title: Code Review Guidelines
---
# Code Review Guidelines
This document outlines the code review process and expectations for the GoMFT project.
## Purpose of Code Reviews
Code reviews serve several important purposes:
- Ensuring code quality and consistency
- Identifying bugs, edge cases, and potential issues early
- Sharing knowledge among team members
- Ensuring adherence to project standards and best practices
- Validating that the implementation meets requirements
## Code Review Process
### 1. Before Requesting a Review
Before requesting a review, ensure your code:
- Passes all automated tests
- Follows the project's coding standards
- Is well-documented
- Includes appropriate tests
- Has a clear, descriptive PR title and description
### 2. Requesting a Review
- Create a pull request against the appropriate branch
- Fill out the PR template completely
- Tag appropriate reviewers based on the code being changed
- Respond to any automated CI/CD feedback
### 3. Conducting a Review
When reviewing code, focus on:
#### Code Quality
- Is the code readable and maintainable?
- Does it follow project conventions and patterns?
- Is the implementation efficient?
- Are edge cases handled appropriately?
#### Functionality
- Does the code meet the requirements?
- Does it handle error conditions properly?
- Is the user experience considered?
#### Testing
- Are there sufficient tests?
- Do tests cover edge cases?
- Are tests reliable (not flaky)?
#### Security
- Are there potential security issues?
- Is user input properly validated?
- Are credentials or sensitive data handled securely?
#### Documentation
- Is the code well-documented?
- Are public APIs clearly documented?
- Is the documentation accurate and up-to-date?
### 4. Providing Feedback
When providing feedback:
- Be specific and clear
- Offer suggestions for improvement
- Differentiate between required changes and optional suggestions
- Provide context or reasoning for requested changes
- Be constructive and respectful
Use these comment prefixes to indicate the severity of feedback:
- **Blocker:** Must be addressed before merging
- **Suggestion:** Recommended improvement, but not required
- **Question:** Request for clarification
- **Nitpick:** Minor style or formatting issue
- **Praise:** Highlight particularly good code
### 5. Responding to Feedback
When receiving review feedback:
- Address all comments
- Explain your reasoning if you disagree with a suggestion
- Ask for clarification if needed
- Thank reviewers for their input
- Mark resolved comments as such
### 6. Approving and Merging
A PR can be merged when:
- It has received approval from at least one reviewer
- All "Blocker" issues are resolved
- All automated checks are passing
- The PR has been rebased on the latest target branch
## Best Practices for Reviewers
### Focus on the Important Things
- Prioritize correctness, security, and maintainability
- Don't get too caught up in style issues that could be automated
- Consider the big picture and overall architecture
### Be Timely
- Try to review PRs within 1-2 business days
- If you can't review promptly, let the author know or reassign
- For urgent fixes, prioritize those reviews
### Be Thorough
- Take the time to understand the code
- Test the code locally if necessary
- Consider edge cases and failure modes
### Be Respectful
- Focus on the code, not the person
- Phrase feedback as suggestions or questions
- Acknowledge good work and improvements
## Best Practices for Authors
### Keep PRs Focused
- Each PR should address a single concern
- Large changes should be broken into smaller, logical PRs
- Avoid unrelated changes in a PR
### Provide Context
- Explain the purpose and approach in the PR description
- Link to relevant issues or documentation
- Point out areas where you're uncertain or would like specific feedback
### Respond Promptly
- Address feedback in a timely manner
- Ask questions if feedback is unclear
- Be open to suggestions and alternatives
### Test Thoroughly
- Test your changes locally before requesting review
- Consider edge cases and error scenarios
- Update tests to cover new functionality
## Special Considerations
### Security-Related Changes
- Security-focused changes require extra scrutiny
- At least one reviewer should have security expertise
- Consider potential attack vectors and edge cases
### API Changes
- Changes to public APIs require careful review
- Consider backward compatibility
- Ensure API changes are well-documented
### Database Changes
- Review for potential performance issues
- Consider migration strategy and backward compatibility
- Validate data integrity considerations
### UI Changes
- Consider accessibility implications
- Review for consistency with design standards
- Test on different devices and screen sizes
## Learning from Code Reviews
Code reviews are a learning opportunity:
- Take note of recurring feedback to improve future code
- Share knowledge gained from reviews with the team
- Use reviews to identify areas where documentation or guides could be improved
## Code Review Checklist
### General
- [ ] Code is well-structured and follows project patterns
- [ ] Variables and functions have clear, descriptive names
- [ ] Comments explain "why" not just "what"
- [ ] Unnecessary code is removed (commented code, debug logs)
- [ ] No hardcoded values that should be configurable
### Go-Specific
- [ ] Error handling is appropriate and consistent
- [ ] Follows Go idioms and best practices
- [ ] Concurrent code is safe and efficient
- [ ] Uses appropriate Go standard library functions
- [ ] Properly handles resources (file handles, connections)
### Frontend-Specific
- [ ] UI is responsive and accessible
- [ ] HTMX usage follows project patterns
- [ ] Templ templates are clean and maintainable
- [ ] JavaScript is minimal and follows best practices
- [ ] CSS follows project conventions
### Testing
- [ ] Tests are included for new functionality
- [ ] Tests cover edge cases and error paths
- [ ] Tests are clear and maintainable
- [ ] Mocks and fixtures are used appropriately
### Security
- [ ] Input validation is thorough
- [ ] No SQL injection vulnerabilities
- [ ] Authentication and authorization are properly implemented
- [ ] Sensitive data is handled securely
### Performance
- [ ] Code is efficient for expected scale
- [ ] Database queries are optimized
- [ ] Appropriate caching is used
- [ ] Resources are used efficiently
Remember that code reviews are a collaborative process aimed at improving the overall quality of the codebase. Both reviewers and authors should approach the process with a growth mindset and mutual respect.
+278
View File
@@ -0,0 +1,278 @@
---
sidebar_position: 2
title: Contributing
---
# Contributing to GoMFT
Thank you for your interest in contributing to GoMFT! This guide will help you get started with contributing to the project.
## Code of Conduct
By participating in this project, you agree to abide by our Code of Conduct. Please read it before contributing.
## Getting Started
### Prerequisites
Before you begin, ensure you have the following installed:
- **Go** (version 1.20 or later)
- **Node.js** (version 18 or later)
- **Git**
- **Docker** (optional, for container-based development)
### Setting Up the Development Environment
1. Fork the repository on GitHub.
2. Clone your forked repository:
```bash
git clone https://github.com/YOUR_USERNAME/GoMFT.git
cd GoMFT
```
3. Add the original repository as an upstream remote:
```bash
git remote add upstream https://github.com/StarFleetCPTN/GoMFT.git
```
4. Install Go dependencies:
```bash
go mod download
```
5. Install Node.js dependencies:
```bash
npm install
```
6. Install the Templ compiler:
```bash
go install github.com/a-h/templ/cmd/templ@latest
```
7. Install Air for live reloading during development:
```bash
go install github.com/cosmtrek/air@latest
```
### Development Workflow
1. Create a new branch for your feature or bug fix:
```bash
git checkout -b feature/your-feature-name
```
2. Make your changes to the codebase.
3. Compile the Templ templates:
```bash
templ generate
```
4. Run the development server with Air:
```bash
air
```
This will start the application with hot reloading enabled, so changes to Go files will trigger a rebuild.
5. For frontend development, compile the Tailwind CSS and watch for changes:
```bash
npm run dev
```
6. Access the application at `http://localhost:8080`.
## Project Structure
See the [Project Structure](/docs/development/project-structure) page for a detailed overview of the codebase organization.
## Coding Guidelines
### Go Code
- Follow the [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) and [Effective Go](https://golang.org/doc/effective_go) guidelines.
- Format your code with `gofmt` or `go fmt`.
- Ensure your code passes `golint` and `go vet`.
- Write tests for your functionality.
- Add comments to exported functions, types, and packages.
### Frontend Code
- Follow the [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) for JavaScript code.
- Use Tailwind CSS for styling.
- Ensure your UI components are responsive.
- Test your UI changes in different browsers.
### Commit Messages
- Use clear and meaningful commit messages.
- Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
- `feat`: A new feature
- `fix`: A bug fix
- `docs`: Documentation only changes
- `style`: Changes that do not affect the meaning of the code
- `refactor`: A code change that neither fixes a bug nor adds a feature
- `test`: Adding missing tests or correcting existing tests
- `chore`: Changes to the build process or auxiliary tools
- `perf`: Performance improvements
Example: `feat: add email notification for failed transfers`
## Testing
### Running Tests
Run the Go tests:
```bash
go test ./...
```
Run specific tests:
```bash
go test ./internal/api/...
```
### Writing Tests
- Write unit tests for your functions and methods.
- Write integration tests for API endpoints.
- Aim for high test coverage, especially for critical functionality.
- Use table-driven tests where appropriate.
## Pull Request Process
1. Update your branch with the latest changes from upstream:
```bash
git fetch upstream
git rebase upstream/main
```
2. Push your branch to your forked repository:
```bash
git push origin feature/your-feature-name
```
3. Create a pull request from your branch to the main repository.
4. Ensure your PR description clearly describes the changes you've made.
5. Link any relevant issues in your PR description.
6. Wait for code review and address any feedback.
### PR Review Checklist
Before submitting your PR, please ensure:
- [ ] Your code builds without errors or warnings
- [ ] You've added tests for your changes
- [ ] All tests pass
- [ ] Your code follows the project's coding guidelines
- [ ] You've updated documentation as needed
- [ ] You've added appropriate logging
- [ ] You've considered security implications
- [ ] Your changes don't introduce performance regressions
## Development Tips
### Working with Templ
[Templ](https://github.com/a-h/templ) is used for HTML templating in GoMFT. After making changes to `.templ` files, you need to regenerate the Go code:
```bash
templ generate
```
### Working with HTMX
[HTMX](https://htmx.org/) is used for dynamic UI updates. Familiarize yourself with its concepts before making UI changes.
### Working with SQLite
GoMFT uses SQLite for data storage. The database file is located at `data/gomft.db` by default. You can use a tool like [SQLite Browser](https://sqlitebrowser.org/) to inspect the database.
### Debugging
For debugging Go code, you can use:
- `fmt.Printf()` statements for simple debugging
- [Delve](https://github.com/go-delve/delve) for more complex debugging scenarios
- VSCode's integrated Go debugger
## Documentation
### Updating Documentation
Documentation is written in Markdown and stored in the `docs/` directory. To update the documentation:
1. Edit the relevant Markdown files.
2. If you're adding new pages, update the sidebar configuration in `sidebars.ts`.
3. Preview your changes using the documentation development server:
```bash
cd documentation
npm install
npm start
```
4. Access the documentation at `http://localhost:3000`.
### API Documentation
API documentation is generated from Go comments using [Swaggo](https://github.com/swaggo/swag). To update the API documentation:
1. Update the API comments following the Swagger/OpenAPI format.
2. Regenerate the API documentation:
```bash
swag init -g cmd/api/main.go
```
## Release Process
GoMFT follows [Semantic Versioning](https://semver.org/).
### Creating a Release
1. Update the version number in relevant files:
- `VERSION` file
- `package.json`
- `internal/version/version.go`
2. Update the CHANGELOG.md file with the new version and its changes.
3. Create a new tag:
```bash
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3
```
4. The CI/CD pipeline will build and publish the release artifacts.
## Getting Help
If you need help with contributing to GoMFT, you can:
- Open an issue on GitHub with questions
- Discuss in the GitHub Discussions section
- Reach out to the maintainers
Thank you for contributing to GoMFT!
+216
View File
@@ -0,0 +1,216 @@
---
sidebar_position: 1
title: Project Structure
---
# Project Structure
This page explains the structure of the GoMFT codebase to help developers understand how the application is organized.
## Overview
GoMFT is built using a combination of Go for the backend and web technologies for the frontend. The application follows a modular architecture to maintain separation of concerns and facilitate testing and maintenance.
## Directory Structure
Here's the high-level directory structure of the GoMFT project:
```
.
├── components/ # Templ components for UI
├── internal/
│ ├── api/ # REST API handlers
│ ├── auth/ # Authentication/authorization
│ ├── config/ # Configuration management
│ ├── db/ # Database models and operations
│ ├── email/ # Email service for notifications and password resets
│ ├── scheduler/ # Job scheduling and execution
│ └── web/ # Web interface handlers
├── static/ # Static assets
│ ├── css/
│ └── js/
└── main.go # Application entry point
```
## Core Components
### Backend (Go)
GoMFT's backend is written in Go and structured around several key packages:
#### `main.go`
The entry point for the application. It initializes the application, loads configuration, sets up the database, and starts the web server.
#### `internal/`
Contains all internal packages that are not intended to be imported by other applications.
- **`api/`**: REST API implementation
- `handlers/`: API request handlers
- `middleware/`: API middleware (authentication, logging, etc.)
- `routes.go`: API route definitions
- **`auth/`**: Authentication and authorization
- `providers/`: Authentication providers (local, LDAP, OAuth)
- `middleware/`: Authentication middleware
- `rbac/`: Role-based access control
- **`config/`**: Configuration management
- `config.go`: Application configuration structure
- `env.go`: Environment variable loading
- `file.go`: Configuration file loading
- **`db/`**: Database layer
- `models/`: Database model definitions
- `migrations/`: Database schema migrations
- `repositories/`: Data access methods
- **`email/`**: Email functionality
- `templates/`: Email templates
- `sender.go`: Email sending service
- **`scheduler/`**: Job scheduling and execution
- `cron.go`: Cron-based job scheduler
- `executor.go`: Transfer job executor
- `queue.go`: Job queue management
- **`web/`**: Web interface
- `handlers/`: Web request handlers
- `middleware/`: Web middleware
- `routes.go`: Web route definitions
#### `components/`
Contains [templ](https://github.com/a-h/templ) components that define the UI. Templ is a Go HTML templating library that provides type-safe templates.
```
components/
├── layouts/ # Page layouts
├── partials/ # Reusable UI components
├── pages/ # Page templates
│ ├── dashboard/
│ ├── transfers/
│ ├── connections/
│ ├── schedules/
│ └── admin/
└── htmx/ # HTMX-specific components
```
### Frontend
The frontend uses a combination of Tailwind CSS for styling and HTMX for dynamic interactions.
#### `static/`
Contains static assets for the web interface:
- **`css/`**: CSS files
- `main.css`: Main stylesheet (compiled from Tailwind)
- **`js/`**: JavaScript files
- `htmx.min.js`: HTMX library
- `alpine.min.js`: Alpine.js for lightweight interactivity
- `app.js`: Application-specific JavaScript
- **`img/`**: Images and icons
## Build System
GoMFT uses several tools to build and bundle the application:
- **Go Build**: Compiles the Go code
- **Templ**: Compiles templ templates to Go code
- **esbuild**: Bundles JavaScript files
- **Tailwind CSS**: Compiles CSS
The build process is orchestrated by a combination of Go commands and npm scripts defined in `package.json`.
## Configuration Files
- **`.air.toml`**: Configuration for Air, a live reload tool for Go
- **`.env.example`**: Example environment variables configuration
- **`go.mod`**: Go module definition
- **`go.sum`**: Go module checksums
- **`package.json`**: npm package definition for frontend dependencies
- **`Dockerfile`**: Docker container definition
- **`docker-compose.yaml`**: Docker Compose configuration
## Database Structure
GoMFT uses GORM (Go Object Relational Mapper) with SQLite as the default database. The main database models include:
- **`User`**: User account information
- **`Role`**: User roles for RBAC
- **`Permission`**: Individual permissions
- **`Connection`**: File transfer connection configurations
- **`Transfer`**: Transfer definitions
- **`Schedule`**: Transfer schedules
- **`History`**: Transfer execution history
- **`Setting`**: Application settings
## API Structure
The REST API follows a RESTful design with these main endpoints:
- **`/api/auth`**: Authentication endpoints
- **`/api/users`**: User management
- **`/api/connections`**: Connection management
- **`/api/transfers`**: Transfer management
- **`/api/schedules`**: Schedule management
- **`/api/history`**: Transfer history
Each endpoint typically supports standard CRUD operations.
## Web Routes
The web interface is organized around these main routes:
- **`/`**: Dashboard
- **`/connections`**: Connection management
- **`/transfers`**: Transfer management
- **`/schedules`**: Schedule management
- **`/history`**: Transfer history
- **`/admin`**: Administrative functions
## Authentication Flow
The authentication flow in GoMFT works like this:
1. User submits credentials via the login form or API
2. Credentials are validated against the configured authentication provider(s)
3. On success, a session is created for web users or a JWT token is issued for API users
4. The user's permissions are loaded based on their role
5. Requests are then authenticated via session cookie or JWT token
## Transfer Execution Flow
The transfer execution flow is as follows:
1. Transfer job is initiated (manually or via scheduler)
2. Job is added to the execution queue
3. Executor picks up the job and prepares the transfer
4. rclone is invoked with the appropriate parameters
5. Progress is monitored and logged
6. Results are recorded in the history
7. Notifications are sent if configured
## Testing Structure
GoMFT includes several types of tests:
- **Unit Tests**: Test individual functions and methods
- **Integration Tests**: Test interactions between components
- **API Tests**: Test API endpoints
- **End-to-End Tests**: Test complete user flows
Tests are organized alongside the code they're testing, following Go conventions.
## Documentation
Documentation is provided in several formats:
- **Code Comments**: Go doc comments for packages and functions
- **API Documentation**: OpenAPI/Swagger documentation for the REST API
- **User Documentation**: User guides and tutorials (this documentation site)
- **README**: Project overview and quick start instructions
+222
View File
@@ -0,0 +1,222 @@
---
sidebar_position: 3
title: Release Process
---
# Release Process
This document outlines the process for creating and publishing new releases of GoMFT.
## Version Numbering
GoMFT follows [Semantic Versioning](https://semver.org/) (SemVer) for version numbering:
- **Major version** (X.0.0): Incompatible API changes or significant architectural changes
- **Minor version** (0.X.0): New features added in a backward-compatible manner
- **Patch version** (0.0.X): Backward-compatible bug fixes and minor improvements
## Release Cycle
GoMFT follows a time-based release cycle:
- **Major releases**: Approximately once per year
- **Minor releases**: Every 2-3 months
- **Patch releases**: As needed for bug fixes and security updates
## Release Preparation
### 1. Feature Freeze
One week before a planned release:
- No new features are merged into the main branch
- Only bug fixes, documentation updates, and release preparation are allowed
- All tests must pass on the main branch
### 2. Update Documentation
- Ensure all new features are properly documented
- Update the changelog with all changes since the last release
- Review and update installation and upgrade instructions
### 3. Version Update
Update version numbers in:
- `VERSION` file in the project root
- `package.json` for frontend dependencies
- `internal/version/version.go` for the Go application
### 4. Create Release Branch
For minor and major releases, create a release branch:
```bash
git checkout -b release/vX.Y.Z
```
This branch will be used for final testing and preparation.
### 5. Update Changelog
Update the `CHANGELOG.md` file with all changes since the last release:
```markdown
# Changelog
## [X.Y.Z] - YYYY-MM-DD
### Added
- New feature 1
- New feature 2
### Changed
- Change 1
- Change 2
### Fixed
- Bug fix 1
- Bug fix 2
### Security
- Security fix 1
```
## Release Process
### 1. Final Testing
Perform the following tests on the release branch:
- Run the full test suite
- Test installation from scratch
- Test upgrading from the previous version
- Test all major features manually
- Test on different platforms (Linux, macOS, Windows)
### 2. Create Release Commit
Once testing is complete, commit the version updates:
```bash
git add VERSION package.json internal/version/version.go CHANGELOG.md
git commit -m "Release vX.Y.Z"
```
### 3. Tag the Release
Create an annotated Git tag for the release:
```bash
git tag -a vX.Y.Z -m "Release vX.Y.Z"
```
### 4. Merge to Main
If using a release branch, merge it back to main:
```bash
git checkout main
git merge release/vX.Y.Z
git push origin main
```
### 5. Push the Tag
Push the tag to trigger the CI/CD release pipeline:
```bash
git push origin vX.Y.Z
```
## Release Artifacts
The CI/CD pipeline automatically builds the following artifacts upon tagging:
1. **Docker Images**:
- `gomft/gomft:vX.Y.Z` - Specific version
- `gomft/gomft:latest` - Updated for stable releases only
2. **Binary Distributions**:
- Linux (amd64, arm64)
- macOS (amd64, arm64)
- Windows (amd64)
3. **Documentation**:
- Updated documentation website with the new version
## Post-Release Tasks
### 1. Create GitHub Release
Create a new release on GitHub:
1. Navigate to the repository's "Releases" page
2. Click "Draft a new release"
3. Select the tag you just pushed
4. Title the release "GoMFT vX.Y.Z"
5. Copy the changelog entry for this version
6. Attach the built artifacts
7. Publish the release
### 2. Announce the Release
Announce the new release through:
- Project website
- GitHub Discussions
- Relevant community forums or mailing lists
### 3. Update Demo Environment
Update the demo/staging environment to the new version to showcase the latest features.
### 4. Version Bump for Development
Create a commit on the main branch that bumps the version to the next anticipated version with a `-dev` suffix:
```bash
# Update versions in files to X.Y.(Z+1)-dev
git add VERSION package.json internal/version/version.go
git commit -m "Bump version to vX.Y.(Z+1)-dev"
git push origin main
```
## Hotfix Releases
For critical issues that need immediate fixes:
1. Create a hotfix branch from the release tag:
```bash
git checkout -b hotfix/vX.Y.(Z+1) vX.Y.Z
```
2. Make the necessary fixes
3. Update version numbers and changelog
4. Follow the standard release process from the "Final Testing" step
## Long-Term Support (LTS)
- Major versions may be designated as LTS releases
- LTS releases receive security updates and critical bug fixes for 12 months after the next major version is released
- Only the most recent major version receives new features
## Release Checklist
Use this checklist for each release:
- [ ] All tests pass on the main branch
- [ ] Documentation is up-to-date
- [ ] CHANGELOG.md is updated
- [ ] Version numbers are updated in all files
- [ ] Release branch created (for minor/major versions)
- [ ] Final testing completed successfully
- [ ] Release committed and tagged
- [ ] Tag pushed to trigger build pipeline
- [ ] GitHub release created with changelog and artifacts
- [ ] Release announced to the community
- [ ] Demo environment updated
- [ ] Development version bumped on main branch
+170
View File
@@ -0,0 +1,170 @@
---
sidebar_position: 4
title: Configuration
---
# Configuration
GoMFT can be customized through environment variables. This document provides a complete list of configuration options available in GoMFT.
## Environment Variables
Environment variables are the primary way to configure GoMFT, especially when running in Docker. These variables can be set in your Docker Compose file, `.env` file, or directly in your system environment.
### Core Configuration
| Variable | Description | Default | Example |
|----------|-------------|---------|---------|
| SERVER_ADDRESS | Server address and port | :8080 | `SERVER_ADDRESS=:9000` |
| DATA_DIR | Main data directory | ./data | `DATA_DIR=/app/data` |
| BACKUP_DIR | Directory for backups | ./backups | `BACKUP_DIR=/app/backups` |
| JWT_SECRET | Secret for JWT tokens | change_this_to_a_secure_random_string | `JWT_SECRET=your-secure-secret-key` |
| BASE_URL | Base URL for GoMFT (used in email links) | http://localhost:8080 | `BASE_URL=https://gomft.example.com` |
| SKIP_SSL_VERIFY | Skip SSL verification for outgoing webhooks/notifications | false | `SKIP_SSL_VERIFY=false` |
### Authentication Configuration
| Variable | Description | Default | Example |
|----------|-------------|---------|---------|
| TOTP_ENCRYPTION_KEY | Encryption key for TOTP secrets | this-is-a-dev-key-not-for-production! | `TOTP_ENCRYPTION_KEY=your-secure-key` |
| PUID | User ID to run as (Docker only) | | `PUID=1000` |
| PGID | Group ID to run as (Docker only) | | `PGID=1000` |
### Email Configuration
| Variable | Description | Default | Example |
|----------|-------------|---------|---------|
| EMAIL_ENABLED | Enable email functionality | false | `EMAIL_ENABLED=true` |
| EMAIL_HOST | SMTP server hostname | smtp.example.com | `EMAIL_HOST=smtp.gmail.com` |
| EMAIL_PORT | SMTP server port | 587 | `EMAIL_PORT=587` |
| EMAIL_USERNAME | SMTP username | user@example.com | `EMAIL_USERNAME=your-email@example.com` |
| EMAIL_PASSWORD | SMTP password | your-password | `EMAIL_PASSWORD=your-smtp-password` |
| EMAIL_FROM_EMAIL | From email address | gomft@example.com | `EMAIL_FROM_EMAIL=gomft@example.com` |
| EMAIL_FROM_NAME | From name | GoMFT | `EMAIL_FROM_NAME=GoMFT Notifications` |
| EMAIL_REPLY_TO | Reply-to email address | | `EMAIL_REPLY_TO=support@example.com` |
| EMAIL_ENABLE_TLS | Use TLS for SMTP connection | true | `EMAIL_ENABLE_TLS=true` |
| EMAIL_REQUIRE_AUTH | Require authentication for SMTP | true | `EMAIL_REQUIRE_AUTH=true` |
### OAuth Configuration (Optional)
| Variable | Description | Default | Example |
|----------|-------------|---------|---------|
| GOOGLE_CLIENT_ID | Google OAuth client ID | | `GOOGLE_CLIENT_ID=your-client-id` |
| GOOGLE_CLIENT_SECRET | Google OAuth client secret | | `GOOGLE_CLIENT_SECRET=your-client-secret` |
## Configuration File
In addition to setting environment variables directly, GoMFT can also be configured using a `.env` file. This file should be placed in the root directory of your GoMFT installation.
Example `.env` file:
```
# Server Configuration
SERVER_ADDRESS=:8080
DATA_DIR=./data
BACKUP_DIR=./backups
JWT_SECRET=change_this_to_a_secure_random_string
BASE_URL=http://localhost:8080
SKIP_SSL_VERIFY=false
# Two-Factor Authentication configuration
TOTP_ENCRYPTION_KEY=this-is-a-dev-key-not-for-production!
# OAuth Configuration (optional)
# GOOGLE_CLIENT_ID=your_google_client_id
# GOOGLE_CLIENT_SECRET=your_google_client_secret
# Email Configuration
EMAIL_ENABLED=true
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_FROM_EMAIL=gomft@example.com
EMAIL_FROM_NAME=GoMFT
EMAIL_REPLY_TO=
EMAIL_ENABLE_TLS=true
EMAIL_REQUIRE_AUTH=true
EMAIL_USERNAME=your-email@example.com
EMAIL_PASSWORD=your-smtp-password
```
## Priority Order
GoMFT uses the following priority order for configuration:
1. Environment variables set directly
2. Variables in the `.env` file
3. Default values
This means that environment variables set directly will override settings in the `.env` file, which in turn override the default values.
## Docker Configuration
When running GoMFT in Docker, you can configure the application in several ways:
### Using Environment Variables
```bash
docker run -d \
--name gomft \
-p 8080:8080 \
-v /path/to/data:/app/data \
-v /path/to/backups:/app/backups \
-e SERVER_ADDRESS=:8080 \
-e JWT_SECRET=your-secure-secret \
-e EMAIL_ENABLED=true \
-e EMAIL_HOST=smtp.example.com \
-e PUID=1000 \
-e PGID=1000 \
starfleetcptn/gomft:latest
```
### Using .env File
```bash
docker run -d \
--name gomft \
-p 8080:8080 \
-v /path/to/data:/app/data \
-v /path/to/backups:/app/backups \
-v /path/to/.env:/app/.env \
starfleetcptn/gomft:latest
```
### Docker Compose Example
```yaml
version: '3'
services:
gomft:
image: starfleetcptn/gomft:latest
container_name: gomft
ports:
- "8080:8080"
volumes:
- ./data:/app/data
- ./backups:/app/backups
- ./.env:/app/.env # Mount .env file (optional)
environment:
- PUID=1000
- PGID=1000
restart: unless-stopped
```
## Applying Configuration Changes
Most configuration changes require a restart of the GoMFT service to take effect. After modifying environment variables or the `.env` file, restart your container or service:
```bash
# For Docker
docker restart gomft
# For Docker Compose
docker-compose restart gomft
```
## Next Steps
- [Docker Deployment](/docs/getting-started/docker) - Advanced Docker deployment options
- [Non-Root Operation](/docs/security/non-root) - Running GoMFT as a non-root user
- [Best Practices](/docs/security/best-practices) - Security best practices
+348
View File
@@ -0,0 +1,348 @@
---
sidebar_position: 3
title: Docker Deployment
---
# Docker Deployment Guide
This guide provides detailed instructions for deploying GoMFT using Docker and Docker Compose, including advanced configuration options and best practices.
## Docker Image Information
GoMFT is available as a Docker image on Docker Hub:
- **Image Name**: `starfleetcptn/gomft`
- **Tags**:
- `latest` - Latest stable release
- `edge` - Latest development build
- `v0.1.0`, `v0.2.0`, etc. - Specific version releases
## Basic Docker Run Command
The simplest way to run GoMFT with Docker:
```bash
docker run -d \
--name gomft \
-p 8080:8080 \
-v $(pwd)/data:/app/data \
-v $(pwd)/backups:/app/backups \
starfleetcptn/gomft:latest
```
## Docker Compose Setup
For a more complete and production-ready setup, use Docker Compose:
```yaml
version: '3'
services:
gomft:
image: starfleetcptn/gomft:latest
container_name: gomft
ports:
- "8080:8080"
volumes:
- ./data:/app/data
- ./backups:/app/backups
environment:
- TZ=UTC
- PUID=1000
- PGID=1000
restart: unless-stopped
```
Save this to a file named `docker-compose.yml` and run:
```bash
docker-compose up -d
```
## Persisting Data
GoMFT stores data in specific directories that should be mounted as volumes:
- **/app/data**: Contains the SQLite database, rclone configurations, and logs
- **/app/backups**: Contains database backups
Example with more specific volume mapping:
```yaml
volumes:
- ./data/db:/app/data/db # Database files
- ./data/configs:/app/data/configs # Rclone config files
- ./data/logs:/app/data/logs # Log files
- ./backups:/app/backups # Backup files
```
## File Transfer Volumes
In addition to the application data, you'll need to mount volumes for the files you want to transfer. These volumes provide GoMFT access to your source files and destination directories.
### Common File Volume Mounts
```yaml
volumes:
# Application data volumes
- ./data:/app/data
- ./backups:/app/backups
# File transfer volumes
- /path/to/source/files:/sftp/files # Source files for transfer
- /path/to/destination:/mft/destination # Destination for transferred files
- /path/to/temp:/mft/temp # Temporary processing directory
```
### Docker Run Example with File Volumes
```bash
docker run -d \
--name gomft \
-p 8080:8080 \
-v $(pwd)/data:/app/data \
-v $(pwd)/backups:/app/backups \
-v /path/to/source/files:/sftp/files \
-v /path/to/destination:/mft/destination \
-v /path/to/temp:/mft/temp \
starfleetcptn/gomft:latest
```
### Docker Compose Example with File Volumes
```yaml
services:
gomft:
image: starfleetcptn/gomft:latest
container_name: gomft
ports:
- "8080:8080"
volumes:
# Application data
- ./data:/app/data
- ./backups:/app/backups
# File transfer directories
- ./source_files:/sftp/files
- ./destination:/mft/destination
- ./temp:/mft/temp
environment:
- TZ=UTC
restart: unless-stopped
```
### Volume Permissions
When mounting file volumes, ensure the container has appropriate permissions to access these directories:
1. If using `PUID` and `PGID` environment variables:
```bash
# Set correct ownership on host directories
chown -R 1000:1000 /path/to/source/files
chown -R 1000:1000 /path/to/destination
chown -R 1000:1000 /path/to/temp
```
2. Or set appropriate permissions:
```bash
# Make directories accessible to the container
chmod -R 755 /path/to/source/files
chmod -R 755 /path/to/destination
chmod -R 755 /path/to/temp
```
## Environment Variables
GoMFT can be configured using environment variables:
### Basic Configuration
```yaml
environment:
- PORT=8080 # Web UI port
- BASE_URL=https://gomft.example.com # Base URL for email links
- TZ=America/New_York # Timezone
```
### Data Directory Configuration
```yaml
environment:
- DATA_DIR=/app/data # Main data directory
- LOGS_DIR=/app/data/logs # Logs directory
- BACKUP_DIR=/app/backups # Backup directory
```
### Email Notification Configuration
```yaml
environment:
- EMAIL_ENABLED=true # Enable email notifications
- EMAIL_HOST=smtp.example.com # SMTP server host
- EMAIL_PORT=587 # SMTP server port
- EMAIL_USER=user@example.com # SMTP username
- EMAIL_PASSWORD=password # SMTP password
- EMAIL_FROM=gomft@example.com # From address for emails
```
### Security Configuration
```yaml
environment:
- JWT_SECRET=your-secret-key # Secret for JWT tokens
- ENCRYPT_KEY=32-char-key # Key for encrypting sensitive data
```
## Running as Non-Root User
For enhanced security, run GoMFT as a non-root user:
```yaml
environment:
- PUID=1000 # User ID to run as
- PGID=1000 # Group ID to run as
```
Make sure your mounted volumes have the appropriate permissions for this user.
## Exposing GoMFT Behind a Reverse Proxy
It's recommended to run GoMFT behind a reverse proxy like Nginx or Traefik for SSL termination and security.
### Nginx Example
```nginx
server {
listen 80;
server_name gomft.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name gomft.example.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
location / {
proxy_pass http://gomft:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### Docker Compose with Traefik Example
```yaml
version: '3'
services:
traefik:
image: traefik:v2.5
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=your@email.com"
- "--certificatesresolvers.myresolver.acme.storage=/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/acme.json
restart: unless-stopped
gomft:
image: starfleetcptn/gomft:latest
volumes:
- ./data:/app/data
- ./backups:/app/backups
environment:
- PUID=1000
- PGID=1000
- BASE_URL=https://gomft.example.com
labels:
- "traefik.enable=true"
- "traefik.http.routers.gomft.rule=Host(`gomft.example.com`)"
- "traefik.http.routers.gomft.entrypoints=websecure"
- "traefik.http.routers.gomft.tls.certresolver=myresolver"
restart: unless-stopped
```
## Health Checks
You can configure a health check to monitor the container's health:
```yaml
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 1m
timeout: 10s
retries: 3
start_period: 30s
```
## Resource Limits
Set resource limits to prevent the container from consuming too many resources:
```yaml
deploy:
resources:
limits:
cpus: '1'
memory: 1G
reservations:
cpus: '0.25'
memory: 512M
```
## Logging Configuration
Configure container logging:
```yaml
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
```
## Troubleshooting Docker Deployment
If you encounter issues with your Docker deployment:
1. Check container logs:
```
docker logs gomft
```
2. Check container status:
```
docker ps -a | grep gomft
```
3. Verify volume permissions:
```
ls -la ./data
```
4. Check container environment:
```
docker exec gomft env
```
5. Inspect the container:
```
docker inspect gomft
```
For more help, refer to the [GitHub repository](https://github.com/StarFleetCPTN/GoMFT) or open an issue.
+190
View File
@@ -0,0 +1,190 @@
---
sidebar_position: 1
title: Installation
---
# Installing GoMFT
GoMFT can be installed using Docker (recommended) or through a traditional installation. This guide covers both methods.
## System Requirements
- **CPU**: 1+ cores (2+ recommended for production)
- **RAM**: 512MB minimum (1GB+ recommended for production)
- **Disk Space**: 100MB for the application plus space for your transfer data and logs
- **Operating System**: Linux, macOS, or Windows with Docker support
## Docker Installation (Recommended)
The easiest way to deploy GoMFT is using Docker. This method handles all dependencies and provides an isolated environment.
### Using Docker Run
```bash
docker run -d \
--name gomft \
-p 8080:8080 \
-v /path/to/data:/app/data \
-v /path/to/backups:/app/backups \
starfleetcptn/gomft:latest
```
Replace `/path/to/data` and `/path/to/backups` with your desired local paths for persistent storage.
### Using Docker Compose
Create a `docker-compose.yaml` file:
```yaml
version: '3'
services:
gomft:
image: starfleetcptn/gomft:latest
container_name: gomft
ports:
- "8080:8080"
volumes:
- ./data:/app/data
- ./backups:/app/backups
environment:
- TZ=UTC
restart: unless-stopped
```
Then run:
```bash
docker-compose up -d
```
### Environment Variables
You can customize your GoMFT installation using environment variables:
```yaml
environment:
- TZ=America/New_York
- PORT=8080
- DATA_DIR=/app/data
- BACKUP_DIR=/app/backups
- LOGS_DIR=/app/data/logs
- EMAIL_ENABLED=false
- BASE_URL=http://localhost:8080
```
See the [Configuration](/docs/getting-started/configuration) section for a complete list of environment variables.
### File Volume Mounts
When running GoMFT in Docker, you'll need to mount volumes to provide access to the files you want to transfer. Here are common volume mount scenarios:
#### For SFTP/FTP Source Files
```bash
-v /path/to/local/files:/sftp/files
```
#### For Destination Directories
```bash
-v /path/to/destination:/mft/destination
```
#### For Processing Temporary Files
```bash
-v /path/to/temp:/mft/temp
```
Example using Docker Run with file volumes:
```bash
docker run -d \
--name gomft \
-p 8080:8080 \
-v /path/to/data:/app/data \
-v /path/to/backups:/app/backups \
-v /path/to/local/files:/sftp/files \
-v /path/to/destination:/mft/destination \
starfleetcptn/gomft:latest
```
Example Docker Compose configuration with file volumes:
```yaml
services:
gomft:
image: starfleetcptn/gomft:latest
container_name: gomft
ports:
- "8080:8080"
volumes:
- ./data:/app/data
- ./backups:/app/backups
- ./source_files:/sftp/files
- ./destination:/mft/destination
- ./temp:/mft/temp
environment:
- TZ=UTC
restart: unless-stopped
```
> **Note**: Ensure the container has appropriate permissions to access the mounted directories. You may need to adjust host-side permissions accordingly.
## Traditional Installation
For environments where Docker is not available or preferred, you can install GoMFT directly.
### Prerequisites
- Go 1.20 or later
- Node.js 18 or later
- gcc (for building SQLite dependencies)
### Building from Source
1. Clone the repository:
```bash
git clone https://github.com/StarFleetCPTN/GoMFT.git
cd GoMFT
```
2. Install Node.js dependencies:
```bash
npm install
```
3. Build the frontend assets:
```bash
npm run build
```
4. Build the Go application:
```bash
go build -o gomft
```
5. Run the application:
```bash
./gomft
```
## Verifying the Installation
After installation, access the GoMFT web interface by navigating to:
```
http://localhost:8080
```
The default login credentials are:
- **Username**: admin
- **Password**: admin
**Important**: Change the default password immediately after the first login for security reasons.
## Next Steps
Once GoMFT is installed, proceed to the [Quick Start](/docs/getting-started/quick-start) guide to begin configuring your file transfers.
+88
View File
@@ -0,0 +1,88 @@
---
sidebar_position: 2
title: Quick Start
---
# GoMFT Quick Start Guide
This guide will help you get up and running with GoMFT quickly. We'll cover logging in, creating your first connection configuration, and setting up a file transfer.
## Accessing the Web Interface
After installation, access the GoMFT web interface at `http://your-server:8080` (or the appropriate port if you've modified it).
1. Log in with the default credentials:
- **Username**: admin@example.com
- **Password**: admin
## Initial Dashboard
The dashboard provides an overview of:
- Recent transfer jobs
- Upcoming scheduled transfers
- System status
- Quick action buttons
![GoMFT Dashboard](/img/dashboard.gomft.png)
## Creating Your First Transfer Configuration
1. Navigate to **Transfer Configurations** in the sidebar menu
2. Click **+ New Configuration**
3. Configure the transfer:
- Select source and destination configurations
- Specify source and destination paths
- Choose the transfer type (Copy, Sync, Move, etc.)
- Configure transfer options (file filtering, bandwidth limits, etc.)
4. Click **Save Transfer**
![Create Transfer](/img/transfer.config.gomft.png)
## Create Your First Scheduled Job
1. Naviagate to **Scheduled Jobs** in the sidebar menu
2. Click **+ New Job**
3. Configure the job:
- Specifiy schedule
- Select Job(s) to run this can be 1 or more
- Change job run order if needed
## Running a Transfer
Once you've created a transfer configuration, you can:
### Run On-Demand
1. Navigate to **Secheduled Jobs**
2. Find your transfer in the list
3. Click the **Run Now** button
4. The transfer will execute immediately
### Schedule a Transfer
1. Navigate to **Schedules**
2. Click **Create New Schedule**
3. Select your transfer configuration
4. Set the schedule using cron syntax or the schedule builder
5. Set additional options (timeout, max retries, etc.)
6. Click **Save Schedule**
## Monitoring Transfers
1. Navigate to **Transfer History** to view all past and ongoing transfers
2. Click on a specific transfer to view detailed information:
- Transfer status
- Start and end times
- Files transferred
- Bytes transferred
- Errors (if any)
- Transfer log
## Next Steps
Now that you've set up your first transfer, explore these additional features:
- [Docker Deployment](/docs/getting-started/docker) - For containerized deployment
- [Traditional Installation](/docs/getting-started/traditional) - For non-Docker environments
- [Transfer Concepts](/docs/core-concepts/transfers) - Learn more about transfer operations
- [Scheduling](/docs/core-concepts/schedules) - Advanced scheduling options
- [Monitoring](/docs/core-concepts/monitoring) - Advanced monitoring capabilities
+325
View File
@@ -0,0 +1,325 @@
---
sidebar_position: 4
title: Traditional Installation
---
# Traditional Installation Guide
This guide covers installing GoMFT directly on your system without using Docker. This approach is useful for environments where containers aren't available or when you need more direct control over the installation.
## System Requirements
- **Operating System**: Linux, macOS, or Windows
- **Go**: Version 1.20 or later
- **Node.js**: Version 18 or later
- **Build Tools**: gcc and related build tools (for SQLite compilation)
## Prerequisites Installation
### On Debian/Ubuntu Linux
```bash
# Install Go
wget https://go.dev/dl/go1.20.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
source ~/.profile
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install build tools
sudo apt-get install -y build-essential
```
### On macOS
```bash
# Using Homebrew
brew install go
brew install node
brew install gcc
```
### On Windows
1. Install Go from [https://golang.org/dl/](https://golang.org/dl/)
2. Install Node.js from [https://nodejs.org/](https://nodejs.org/)
3. Install Build Tools for Visual Studio
## Building GoMFT from Source
1. Clone the repository:
```bash
git clone https://github.com/StarFleetCPTN/GoMFT.git
cd GoMFT
```
2. Install Node.js dependencies and build the frontend:
```bash
npm install
npm run build
```
3. Compile the Go application:
```bash
go build -o gomft main.go
```
## Installation Options
### Option 1: Run Directly
After building, you can run the application directly:
```bash
./gomft
```
### Option 2: Install as a System Service
#### On Linux (systemd)
Create a systemd service file:
```bash
sudo nano /etc/systemd/system/gomft.service
```
Add the following content:
```ini
[Unit]
Description=GoMFT - Go Managed File Transfer
After=network.target
[Service]
Type=simple
User=gomft
Group=gomft
WorkingDirectory=/opt/gomft
ExecStart=/opt/gomft/gomft
Restart=on-failure
RestartSec=5s
Environment="PORT=8080"
Environment="DATA_DIR=/var/lib/gomft/data"
Environment="BACKUP_DIR=/var/lib/gomft/backups"
Environment="LOGS_DIR=/var/log/gomft"
[Install]
WantedBy=multi-user.target
```
Create a dedicated user and set up directories:
```bash
# Create user
sudo useradd -r -s /bin/false gomft
# Create directories
sudo mkdir -p /opt/gomft /var/lib/gomft/data /var/lib/gomft/backups /var/log/gomft
# Copy application
sudo cp -r * /opt/gomft/
# Set permissions
sudo chown -R gomft:gomft /opt/gomft /var/lib/gomft /var/log/gomft
```
Enable and start the service:
```bash
sudo systemctl enable gomft
sudo systemctl start gomft
```
#### On macOS (launchd)
Create a launchd plist file:
```bash
sudo nano /Library/LaunchDaemons/com.gomft.plist
```
Add the following content:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.gomft</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/gomft/gomft</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>WorkingDirectory</key>
<string>/usr/local/gomft</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>8080</string>
<key>DATA_DIR</key>
<string>/var/lib/gomft/data</string>
<key>BACKUP_DIR</key>
<string>/var/lib/gomft/backups</string>
<key>LOGS_DIR</key>
<string>/var/log/gomft</string>
</dict>
</dict>
</plist>
```
Set up directories and install:
```bash
# Create directories
sudo mkdir -p /usr/local/gomft /var/lib/gomft/data /var/lib/gomft/backups /var/log/gomft
# Copy application
sudo cp -r * /usr/local/gomft/
# Set permissions
sudo chown -R $(whoami):staff /usr/local/gomft /var/lib/gomft /var/log/gomft
# Load service
sudo launchctl load /Library/LaunchDaemons/com.gomft.plist
```
#### On Windows (Windows Service)
1. Install [NSSM (Non-Sucking Service Manager)](https://nssm.cc/download)
2. Open Command Prompt as Administrator
3. Create the service:
```bat
nssm install GoMFT C:\path\to\gomft.exe
nssm set GoMFT AppDirectory C:\path\to\gomft\directory
nssm set GoMFT AppEnvironmentExtra PORT=8080 DATA_DIR=C:\ProgramData\GoMFT\data BACKUP_DIR=C:\ProgramData\GoMFT\backups LOGS_DIR=C:\ProgramData\GoMFT\logs
nssm start GoMFT
```
## Configuration
### Environment Variables
Create a `.env` file in the application directory or set system environment variables:
```
PORT=8080
DATA_DIR=/var/lib/gomft/data
BACKUP_DIR=/var/lib/gomft/backups
LOGS_DIR=/var/log/gomft
BASE_URL=http://localhost:8080
EMAIL_ENABLED=false
JWT_SECRET=your-secret-key
ENCRYPT_KEY=32-character-encryption-key
```
### Web Server Setup
For production use, it's recommended to run GoMFT behind a web server like Nginx:
#### Nginx Configuration
```nginx
server {
listen 80;
server_name your-gomft-server.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
## Updating GoMFT
To update a traditionally installed GoMFT:
1. Stop the service:
```bash
sudo systemctl stop gomft # For Linux
sudo launchctl unload /Library/LaunchDaemons/com.gomft.plist # For macOS
nssm stop GoMFT # For Windows
```
2. Back up your data:
```bash
cp -r /var/lib/gomft/data /var/lib/gomft/data.backup
```
3. Get the latest code:
```bash
cd /path/to/gomft/source
git pull
```
4. Rebuild:
```bash
npm install
npm run build
go build -o gomft main.go
```
5. Update the installation:
```bash
sudo cp gomft /opt/gomft/ # For Linux
sudo cp gomft /usr/local/gomft/ # For macOS
copy gomft.exe C:\path\to\gomft.exe # For Windows
```
6. Restart the service:
```bash
sudo systemctl start gomft # For Linux
sudo launchctl load /Library/LaunchDaemons/com.gomft.plist # For macOS
nssm start GoMFT # For Windows
```
## Troubleshooting
### Common Issues
1. **Permission Errors**:
- Check that the user running GoMFT has write permissions to the data, backup, and logs directories.
2. **Database Errors**:
- Ensure the SQLite database path is writeable.
- Check database integrity: `sqlite3 /var/lib/gomft/data/gomft.db "PRAGMA integrity_check;"`
3. **Port Already in Use**:
- Change the port in the configuration.
- Check what's using port 8080: `sudo lsof -i :8080`
4. **Missing Dependencies**:
- Make sure all required Go and Node.js dependencies are installed.
### Viewing Logs
- **Application Logs**: Check `/var/log/gomft/` or your configured logs directory
- **System Service Logs**:
```bash
# For Linux
journalctl -u gomft
# For macOS
log show --predicate 'senderImagePath contains "gomft"'
# For Windows
Get-EventLog -LogName Application -Source GoMFT
```
For more help, refer to the [GitHub repository](https://github.com/StarFleetCPTN/GoMFT) or open an issue.
+78
View File
@@ -0,0 +1,78 @@
---
sidebar_position: 2
title: Features
---
# GoMFT Features
GoMFT offers a comprehensive set of features that make it a powerful solution for managed file transfers. Here's a detailed breakdown of what GoMFT offers:
## Core Features
### Multi-Protocol Support
GoMFT leverages rclone to support a wide range of storage providers and protocols:
- **Cloud Storage**: Amazon S3, Google Cloud Storage
- **Object Storage**: MinIO, Backblaze B2, Wasabi
- **FTP/SFTP**: FTP, FTPS, SFTP servers
- **WebDAV**: WebDAV servers and services
- **Local Storage**: Local disk, SMB/CIFS shares
- **And many more**: Over 40 storage systems supported
### Intuitive Web Interface
- **Clean, Modern UI**: Easy-to-use web interface built with Tailwind CSS and HTMX
- **Dashboard**: Overview of recent transfers, scheduled jobs, and system status
- **Configuration Manager**: Visual interface for creating and editing transfer configurations
- **Job Scheduler**: Interface for creating and managing scheduled jobs
- **Transfer Logs**: Detailed logs of all transfer operations
- **Dark Mode**: Support for light and dark themes
### Powerful Scheduling
- **Cron-style Scheduling**: Set up transfers using familiar cron syntax
- **Recurring Transfers**: Schedule transfers to run on a regular basis
- **One-time Transfers**: Run transfers immediately or at a specific time
- **Schedule Grouping**: Organize schedules into logical groups
- **Priority Control**: Set priority levels for scheduled tasks
## Advanced Features
### Transfer Options
- **Bidirectional Sync**: Synchronize files in both directions
- **File Filtering**: Include or exclude files based on patterns
- **Bandwidth Limiting**: Restrict bandwidth usage for transfers
- **Parallel Transfers**: Configure the number of simultaneous transfers
- **Delta Transfers**: Transfer only changed parts of files
- **Checksumming**: Verify file integrity during transfers
### Notification System
- **Notifications**: Receive alerts when transfers complete or fail
- **Custom Templates**: Customize notification content and format
- **Notification Rules**: Configure which events trigger notifications
- **Notification Providers**: Webhooks, Ntfy, Gotify, Pushover, Pushbullet
### Admin Tools
- **User Management**: Create and manage users with different roles
- **Role-Based Access Control**: Control access to different parts of the application
- **Audit Logging**: Track user actions for security and compliance
- **System Monitoring**: Monitor system performance and resource usage
- **Database Backup/Restore**: Back up and restore the application database
- **Log Viewer**: Browse and search through application logs
### Security Features
- **Authentication**: Secure login with optional MFA support
- **Encryption**: Encrypt data in transit and at rest
- **Secure Credential Storage**: Safely store connection credentials
- **Non-Root Container Support**: Run containers as non-root users for enhanced security
## Integration Capabilities
- **Docker Support**: Easy deployment with Docker containers
- **Docker Compose**: Multi-container deployment using Docker Compose
- **Reverse Proxy Compatible**: Works behind reverse proxies like Nginx or Traefik
+39
View File
@@ -0,0 +1,39 @@
---
sidebar_position: 1
title: Overview
---
# GoMFT Overview
GoMFT is a modern, web-based managed file transfer solution written in Go. It provides an intuitive interface for setting up, scheduling, and monitoring file transfers across various storage backends.
## What is GoMFT?
GoMFT (Go Managed File Transfer) is an open-source file transfer platform that enables reliable, secure, and automated file transfers. Built on top of the powerful [rclone](https://rclone.org/) engine, GoMFT provides a user-friendly web interface that makes it easy to configure and manage complex file transfer operations.
## Key Benefits
- **User-Friendly Interface**: Intuitive web UI for configuring and monitoring file transfers
- **Multi-Protocol Support**: Transfer files using SFTP, S3, Google Drive, and many more protocols
- **Automated Scheduling**: Set up recurring transfers with flexible scheduling options
- **Comprehensive Logging**: Detailed logs for troubleshooting and audit purposes
- **Notifications**: Get alerts when transfers succeed or fail
- **Docker Support**: Easy deployment with Docker containers
- **Security**: Role-based access control and secure credential management
## Use Cases
- **Data Synchronization**: Keep files in sync across different storage systems
- **Backup and Archiving**: Automate backup processes to cloud or local storage
- **Secure File Exchange**: Transfer files securely between organizations
- **Cloud Migration**: Move data between different cloud providers
- **Workflow Automation**: Trigger file transfers as part of larger workflows
- **Compliance**: Maintain audit logs for regulatory compliance
GoMFT is designed to be simple to deploy and use, while providing the reliability and features needed for enterprise file transfer needs.
## Community Support
Join our Discord community for support, discussions, and updates about GoMFT:
<a href="https://discord.gg/f9dwtM3j" className="discord-badge">Join Discord Community</a>
+158
View File
@@ -0,0 +1,158 @@
---
sidebar_position: 2
title: Authentication
---
# Authentication and Authorization
GoMFT provides robust authentication and authorization mechanisms to ensure secure access to the application and its features. This page explains how to configure and manage authentication in GoMFT.
## Authentication Methods
GoMFT supports multiple authentication methods to secure access to the application:
### Local Authentication
The default authentication method using GoMFT's built-in user database:
- **Username/Password**: Traditional username and password authentication
- **Password Requirements**: Configurable password complexity rules
- **Password Expiration**: Force password changes after a configurable period
- **Account Lockout**: Temporarily lock accounts after failed login attempts
### OAuth/OpenID Connect
Support for modern identity providers:
- **Single Sign-On**: Integrate with SSO solutions
- **Identity Providers**: Support for popular providers (Google, Microsoft, Okta, etc.)
- **JWT Tokens**: Secure token-based authentication
- **Automatic Account Provisioning (COMING SOON)**: Create GoMFT accounts based on SSO information
## Setting Up Authentication
### Configuring Local Authentication
Local authentication is enabled by default and requires minimal setup:
### Configuring OAuth/OpenID Connect
To set up OAuth or OpenID Connect:
1. Navigate to **Settingss** > **Authentication Providers**
2. Select **OAuth/OIDC** as an authentication method
3. Configure provider settings:
- Provider URL
- Client ID
- Client Secret
- Scope (e.g., `openid profile email`)
- Callback URL
4. Set up attribute mappings:
- Map provider attributes to GoMFT user properties
- Configure role attribute or claim
5. Test the configuration
## Multi-Factor Authentication (MFA)
GoMFT supports multi-factor authentication for enhanced security:
### MFA Options
- **Time-based One-Time Password (TOTP)**: Compatible with apps like Google Authenticator
- **Email Verification Codes**: One-time codes sent via email
- **Recovery Codes**: Backup codes for emergency access
### Enabling MFA
For users to set up MFA:
1. Log in to GoMFT
2. Navigate to **Profile** > **Security Settings**
3. Select **Enable Multi-Factor Authentication**
4. Choose the MFA method (e.g., TOTP)
5. Follow the setup instructions:
- For TOTP: Scan QR code with authenticator app
- For Email: Verify email address
6. Generate and save recovery codes
## User Management
### Creating Users
To create new users:
1. Navigate to **Administration** > **Users**
2. Click **Create New User**
3. Fill in the user details:
- Username
- Email address
- Full name
- Initial password or send password reset link
- Role assignment
4. Click **Create Users**
### Managing User Accounts
To manage existing users:
1. Navigate to **Administration** > **Users**
2. Find the user in the list
3. Available actions:
- Edit user details
- Change role assignment
- Reset password
- Enable/disable account
- Force MFA enrollment
- Delete user
### User Self-Service
GoMFT provides self-service features for users:
- **Profile Management**: Users can update their profile information
- **Password Change**: Users can change their password
- **MFA Setup**: Users can configure their MFA preferences
## Role-Based Access Control
GoMFT implements role-based access control (RBAC) to manage permissions:
### Default Roles
- **Administrator**: Full access to all system features
- **System**: Can manage transfers and connections but not admin settings
- **User**: Basic access to create and manage personal transfers
### Creating Custom Roles
To create a custom role:
1. Navigate to **Administration** > **Roles**
2. Click **Create New Role**
3. Define the role:
- Role name
- Description
- Permission assignments
4. Save the role
### Permission Categories
GoMFT organizes permissions into categories:
- **System Administration**: System-wide settings and maintenance
- **User Management**: User and role administration
- **Transfer Management**: Creating and managing transfers
- **Connection Management**: Creating and managing connections
- **Schedule Management**: Managing transfer schedules
- **Execution Control**: Running and controlling transfers
- **Monitoring**: Viewing logs and reports
## Security Best Practices
- **Enforce Strong Passwords**: Configure strong password requirements
- **Enable MFA**: Require MFA for all users, especially administrators
- **Regular Review**: Periodically review user accounts and permissions
- **Principle of Least Privilege**: Assign the minimum necessary permissions
- **Audit Authentication**: Monitor and audit authentication events
- **Secure Configuration**: Properly secure authentication configuration files
- **Account Lifecycle**: Implement processes for account creation and termination
+187
View File
@@ -0,0 +1,187 @@
---
sidebar_position: 1
title: Security Best Practices
---
# Security Best Practices
This guide provides recommendations for securing your GoMFT installation and maintaining a secure file transfer environment.
## Installation Security
### Use Docker Security Features
When deploying GoMFT with Docker:
- **Run as Non-Root**: Always run the container as a non-root user (see [Running as Non-Root](/docs/security/non-root))
- **Use Read-Only Filesystem**: Mount the filesystem as read-only except for specific data directories
- **Limit Capabilities**: Use Docker's `--cap-drop` to limit container capabilities
- **Set Resource Limits**: Prevent resource exhaustion with memory and CPU limits
- **Use Docker Secrets**: Store sensitive configuration in Docker secrets instead of environment variables
Example secure docker-compose configuration:
```yaml
services:
gomft:
image: starfleetcptn/gomft:latest
user: "1000:1000"
read_only: true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
volumes:
- ./data:/app/data
- ./backups:/app/backups
environment:
- TZ=UTC
deploy:
resources:
limits:
cpus: '1'
memory: 1G
```
### Traditional Installation Security
For traditional installations:
- **Dedicated User**: Create a dedicated system user for running GoMFT
- **Minimal Permissions**: Give the user only the permissions it needs
- **Firewall Rules**: Restrict access to only necessary ports
- **SELinux/AppArmor**: Use system security modules to limit application scope
## Network Security
### Use HTTPS
Always use HTTPS for the web interface:
- **Configure TLS**: Use a reverse proxy like Nginx or Traefik for TLS termination
- **Strong Ciphers**: Use modern, secure cipher suites
- **HSTS**: Enable HTTP Strict Transport Security
- **Valid Certificates**: Use trusted certificates from Let's Encrypt or other providers
### Access Control
- **IP Restrictions**: Limit access to trusted IP addresses where possible
- **VPN Access**: Consider placing GoMFT behind a VPN for additional security
- **Firewall Rules**: Configure firewall rules to restrict access to essential ports only
## Authentication and Authorization
### Strong Authentication
- **Password Policy**: Enforce strong password requirements
- **MFA**: Enable Multi-Factor Authentication for all users
- **Session Management**: Set appropriate session timeouts
- **Failed Login Limits**: Implement account lockouts after several failed attempts
### Role-Based Access Control
- **Principle of Least Privilege**: Grant users only the permissions they need
- **Separation of Duties**: Use roles to separate administrative functions
- **Regular Review**: Periodically review user roles and permissions
## Credential Management
### Secure Storage
- **Encrypted Credentials**: Ensure all credentials are encrypted at rest
- **Isolated Storage**: Store sensitive credentials in a separate database or secure storage
- **Key Rotation**: Regularly rotate encryption keys
### Credential Practices
- **Service Accounts**: Use service accounts instead of personal accounts for connections
- **Temporary Credentials**: Use temporary credentials where supported (e.g., AWS STS)
- **API Keys**: Regularly rotate API keys and access tokens
- **Minimal Scope**: Grant credentials the minimum required permissions
## Transfer Security
### Secure Protocols
- **Choose Secure Protocols**: Prefer SFTP, FTPS, or HTTPS over unencrypted protocols
- **Disable Legacy Protocols**: Disable insecure protocols like FTP where possible
- **Strong Ciphers**: Configure secure cipher suites for encrypted protocols
### Data Handling
- **Data Classification**: Classify data by sensitivity and apply appropriate controls
- **Data Validation**: Validate files before processing them
- **Virus Scanning**: Implement virus scanning for transferred files
- **Data Loss Prevention**: Consider DLP measures for sensitive data
## Auditing and Monitoring
### Comprehensive Logging
- **Detailed Logs**: Enable detailed logging for all operations
- **Secure Log Storage**: Store logs securely with access controls
- **Log Rotation**: Implement log rotation to manage disk space
- **Tamper Protection**: Ensure logs cannot be modified or deleted
### Monitoring and Alerting
- **Real-time Monitoring**: Monitor for suspicious activities
- **Security Alerts**: Configure alerts for security-related events
- **Performance Monitoring**: Watch for performance issues that might indicate attacks
- **Regular Review**: Establish a process for regular log review
## System Security
### Regular Updates
- **Update GoMFT**: Keep GoMFT updated to the latest version
- **Patch Host System**: Keep the host operating system patched
- **Update Dependencies**: Keep all dependencies (Docker, etc.) updated
### Backup and Recovery
- **Regular Backups**: Back up the GoMFT database and configurations regularly
- **Secure Backups**: Encrypt backups and store them securely
- **Test Restoration**: Regularly test backup restoration
- **Disaster Recovery Plan**: Create and maintain a disaster recovery plan
## Periodic Security Review
### Security Assessments
- **Vulnerability Scanning**: Regularly scan for vulnerabilities
- **Penetration Testing**: Conduct periodic penetration tests
- **Configuration Review**: Review security configurations regularly
- **Compliance Checks**: Ensure ongoing compliance with relevant standards
### Documentation
- **Security Policies**: Document security policies and procedures
- **Configuration Documentation**: Maintain documentation of secure configurations
- **Incident Response Plan**: Create and maintain an incident response plan
## Integrating with Security Tools
GoMFT can be integrated with external security tools:
- **SIEM Integration**: Forward logs to Security Information and Event Management tools
- **Vulnerability Scanners**: Include GoMFT in vulnerability scanning
- **Compliance Tools**: Integrate with compliance monitoring tools
## Best Practices for Specific Environments
### Cloud Deployment
- **Cloud Security Services**: Utilize cloud provider security services
- **Network Security Groups**: Configure appropriate network security groups
- **Private Endpoints**: Use private endpoints where possible
- **Cloud IAM**: Leverage cloud Identity and Access Management
### On-Premises Deployment
- **Network Segmentation**: Place GoMFT in an appropriate network segment
- **Physical Security**: Ensure physical security of the servers
- **Environmental Controls**: Implement appropriate environmental controls
- **Backup Power**: Ensure backup power for critical systems
+235
View File
@@ -0,0 +1,235 @@
---
sidebar_position: 3
title: Running as Non-Root
---
# Running GoMFT as a Non-Root User
By default, Docker containers run as the root user, which can pose security risks. GoMFT fully supports running as a non-root user, which is recommended for production environments.
## Benefits of Running as Non-Root
- **Improved Security**: Limits the potential damage if the container is compromised
- **Better File Permissions**: Files created by the container will match your host user permissions
- **Compliance**: Many security policies and best practices require containers to run as non-root
## Methods to Run GoMFT as Non-Root
GoMFT supports several methods for running as a non-root user, each with its own advantages.
### Method 1: Using PUID/PGID Environment Variables (Recommended)
This method allows changing the user at runtime without rebuilding the image:
```bash
# Using current user's ID
docker run -e PUID=$(id -u) -e PGID=$(id -g) starfleetcptn/gomft:latest
```
Or in docker-compose.yml:
```yaml
services:
gomft:
image: starfleetcptn/gomft:latest
environment:
- PUID=1000 # Your user ID
- PGID=1000 # Your group ID
volumes:
- ./data:/app/data
- ./backups:/app/backups
```
### Method 2: Using the `--user` Flag with Docker Run
This method is simple but doesn't support some advanced features like permission fixing:
```bash
docker run --user $(id -u):$(id -g) starfleetcptn/gomft:latest
```
### Method 3: Using Docker Compose with Environment Variables
This approach uses environment variables from the host for the user directive:
```yaml
services:
gomft:
image: starfleetcptn/gomft:latest
user: "${UID:-1000}:${GID:-1000}"
volumes:
- ./data:/app/data
- ./backups:/app/backups
```
Run with:
```bash
UID=$(id -u) GID=$(id -g) docker-compose up -d
```
### Method 4: Building a Custom Image with Specified UID/GID
This method builds a custom image with your specified user ID:
```dockerfile
FROM starfleetcptn/gomft:latest
ARG UID=1000
ARG GID=1000
RUN usermod -u $UID gomft && groupmod -g $GID gomft
```
In docker-compose.yml:
```yaml
services:
gomft:
build:
context: .
args:
UID: ${UID:-1000}
GID: ${GID:-1000}
```
## Environment Variables for User Management
| Variable | Description | Default |
| -------- | ------------------ | ------------------------ |
| PUID | User ID to run as | Built-in user ID (1000) |
| PGID | Group ID to run as | Built-in group ID (1000) |
| USERNAME | Username to use | gomft |
## Volume Permissions
When running as a non-root user, ensure that the directories on the host have appropriate permissions for the container user:
### Option 1: Create Directories with Correct Ownership (Recommended)
```bash
# Create directories
mkdir -p data backups
# Set ownership to match the PUID/PGID you'll use
chown -R 1000:1000 data backups
```
### Option 2: Adjust Permissions (Less Secure, but Easier for Testing)
```bash
mkdir -p data backups
chmod -R 777 data backups
```
## Verifying Non-Root Operation
To verify that GoMFT is running as a non-root user:
```bash
docker exec gomft id
```
You should see output showing the UID and GID you specified.
## Troubleshooting Permission Issues
### Common Issues
1. **Volume Mount Permission Denied**: The container user doesn't have permission to access mounted volumes
**Solution**:
```bash
chown -R <PUID>:<PGID> ./data ./backups
```
2. **Cannot Write to Log Files**: Permission issues with log files
**Solution**:
```bash
# Ensure log directory exists and has correct permissions
mkdir -p ./data/logs
chown -R <PUID>:<PGID> ./data/logs
```
3. **Database Permission Errors**: SQLite database permissions
**Solution**:
```bash
# Check and fix database file permissions
chown <PUID>:<PGID> ./data/gomft.db
chmod 644 ./data/gomft.db
```
### Checking Container Logs for Permission Issues
```bash
docker logs gomft | grep -i "permission denied"
```
### Volume Permission Script
You can use this script to fix permissions on your data volumes:
```bash
#!/bin/bash
# Fix permissions for GoMFT volumes
# Set your PUID and PGID here
PUID=1000
PGID=1000
# Create directories if they don't exist
mkdir -p ./data ./backups
# Fix ownership
chown -R $PUID:$PGID ./data ./backups
echo "Permissions fixed for GoMFT volumes"
```
## Security Considerations
When running as non-root, there are still some security considerations:
- Avoid using `chmod 777` in production environments
- Use volume binding with caution, especially for sensitive data
- Consider using Docker secrets for sensitive credentials
- Regularly update your GoMFT image to get the latest security fixes
- Implement network segmentation to limit the container's access
## Example: Complete Docker Compose Setup with Non-Root User
```yaml
version: '3.8'
services:
gomft:
image: starfleetcptn/gomft:latest
container_name: gomft
environment:
- PUID=1000
- PGID=1000
- TZ=UTC
- BASE_URL=http://localhost:8080
volumes:
- ./data:/app/data
- ./backups:/app/backups
ports:
- "8080:8080"
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 1m
timeout: 10s
retries: 3
start_period: 30s
```
## Best Practices Summary
1. **Always run GoMFT as a non-root user in production**
2. **Use PUID/PGID environment variables for flexible user mapping**
3. **Set appropriate permissions on volume mounts**
4. **Verify the container is running as the expected user**
5. **Follow least privilege principles for the container user**
+162
View File
@@ -0,0 +1,162 @@
import {themes as prismThemes} from 'prism-react-renderer';
import type {Config} from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
const config: Config = {
title: 'GoMFT',
tagline: 'A modern, web-based managed file transfer solution',
favicon: 'favicon.ico',
// Set the production url of your site here
url: 'https://starfleetcptn.github.io',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/GoMFT/',
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'StarFleetCPTN', // Usually your GitHub org/user name.
projectName: 'GoMFT', // Usually your repo name.
deploymentBranch: 'gh-pages',
trailingSlash: false,
onBrokenLinks: 'warn',
onBrokenMarkdownLinks: 'warn',
// Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you
// may want to replace "en" with "zh-Hans".
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
presets: [
[
'classic',
{
docs: {
sidebarPath: './sidebars.ts',
// Please change this to your repo.
editUrl:
'https://github.com/StarFleetCPTN/GoMFT/tree/main/documentation',
},
blog: {
showReadingTime: true,
// Please change this to your repo.
editUrl:
'https://github.com/StarFleetCPTN/GoMFT/tree/main/documentation',
},
theme: {
customCss: './src/css/custom.css',
},
} satisfies Preset.Options,
],
],
// Add the local search plugin
plugins: [
[
require.resolve('@easyops-cn/docusaurus-search-local'),
{
// Whether to also index the docs/blog not written in the current language (false by default)
indexDocs: true,
indexBlog: true,
// Whether to also add the language name to the document ID, to differentiate documents with the same ID but different languages (false by default)
language: ['en'],
// Optional: path to a file containing a list of words to be highlighted in the search results (empty by default)
highlightSearchTermsOnTargetPage: true,
},
],
],
themeConfig: {
// Replace with your project's social card
image: 'img/gomft-social-card.jpg',
navbar: {
title: 'GoMFT',
logo: {
alt: 'GoMFT Logo',
src: 'img/logo.svg',
},
items: [
{
type: 'docSidebar',
sidebarId: 'docsSidebar',
position: 'left',
label: 'Documentation',
},
{to: '/docs/introduction/overview', label: 'Getting Started', position: 'left'},
{to: '/docs/development/contributing', label: 'Contributing', position: 'left'},
{
href: 'https://github.com/StarFleetCPTN/GoMFT',
label: 'GitHub',
position: 'right',
},
{
href: 'https://discord.gg/f9dwtM3j',
className: 'header-discord-link',
'aria-label': 'Discord community',
position: 'right',
},
],
},
footer: {
style: 'dark',
links: [
{
title: 'Documentation',
items: [
{
label: 'Introduction',
to: '/docs/introduction/overview',
},
{
label: 'Installation',
to: '/docs/getting-started/installation',
},
{
label: 'Features',
to: '/docs/introduction/features',
},
],
},
{
title: 'Community',
items: [
{
label: 'Discord',
href: 'https://discord.gg/f9dwtM3j',
},
{
label: 'GitHub Discussions',
href: 'https://github.com/StarFleetCPTN/GoMFT/discussions',
},
{
label: 'Issues',
href: 'https://github.com/StarFleetCPTN/GoMFT/issues',
},
],
},
{
title: 'More',
items: [
{
label: 'GitHub',
href: 'https://github.com/StarFleetCPTN/GoMFT',
},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} GoMFT. Built with Docusaurus.`,
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
} satisfies Preset.ThemeConfig,
};
export default config;
+18448
View File
File diff suppressed because it is too large Load Diff
+49
View File
@@ -0,0 +1,49 @@
{
"name": "go-mft-docs",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc",
"deploy-gh-pages": "GIT_USER=StarFleetCPTN USE_SSH=true yarn deploy"
},
"dependencies": {
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@easyops-cn/docusaurus-search-local": "^0.49.2",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/tsconfig": "3.7.0",
"@docusaurus/types": "3.7.0",
"typescript": "~5.6.2"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome version",
"last 3 firefox version",
"last 5 safari version"
]
},
"engines": {
"node": ">=18.0"
}
}
+58
View File
@@ -0,0 +1,58 @@
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
const sidebars: SidebarsConfig = {
docsSidebar: [
{
type: 'category',
label: 'Introduction',
items: ['introduction/overview', 'introduction/features'],
},
{
type: 'category',
label: 'Getting Started',
items: ['getting-started/installation', 'getting-started/configuration', 'getting-started/quick-start', 'getting-started/docker', 'getting-started/traditional'],
},
{
type: 'category',
label: 'Core Concepts',
items: ['core-concepts/transfers', 'core-concepts/connections', 'core-concepts/schedules', 'core-concepts/monitoring'],
},
{
type: 'category',
label: 'Advanced Features',
items: [
'advanced/notifications-overview',
'advanced/gotify-notifications',
'advanced/ntfy-notifications',
'advanced/pushbullet-notifications',
'advanced/pushover-notifications',
'advanced/webhook-notifications',
'advanced/admin-tools'
],
},
{
type: 'category',
label: 'Security',
items: ['security/best-practices', 'security/authentication', 'security/non-root'],
},
{
type: 'category',
label: 'Development',
items: ['development/project-structure', 'development/contributing'],
},
],
};
export default sidebars;
@@ -0,0 +1,71 @@
import type {ReactNode} from 'react';
import clsx from 'clsx';
import Heading from '@theme/Heading';
import styles from './styles.module.css';
type FeatureItem = {
title: string;
Svg: React.ComponentType<React.ComponentProps<'svg'>>;
description: ReactNode;
};
const FeatureList: FeatureItem[] = [
{
title: 'Easy to Use',
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
description: (
<>
Docusaurus was designed from the ground up to be easily installed and
used to get your website up and running quickly.
</>
),
},
{
title: 'Focus on What Matters',
Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
description: (
<>
Docusaurus lets you focus on your docs, and we&apos;ll do the chores. Go
ahead and move your docs into the <code>docs</code> directory.
</>
),
},
{
title: 'Powered by React',
Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
description: (
<>
Extend or customize your website layout by reusing React. Docusaurus can
be extended while reusing the same header and footer.
</>
),
},
];
function Feature({title, Svg, description}: FeatureItem) {
return (
<div className={clsx('col col--4')}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<Heading as="h3">{title}</Heading>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures(): ReactNode {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}
@@ -0,0 +1,11 @@
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureSvg {
height: 200px;
width: 200px;
}
+206
View File
@@ -0,0 +1,206 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
:root {
--ifm-color-primary: #2e6db8;
--ifm-color-primary-dark: #2962a6;
--ifm-color-primary-darker: #275c9c;
--ifm-color-primary-darkest: #204c81;
--ifm-color-primary-light: #3378ca;
--ifm-color-primary-lighter: #3e7fcf;
--ifm-color-primary-lightest: #5a92d6;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
/* Custom colors */
--ifm-color-secondary: #54b4d3;
--ifm-color-success: #28a745;
--ifm-color-info: #54b4d3;
--ifm-color-warning: #ffc107;
--ifm-color-danger: #dc3545;
/* Font settings */
--ifm-font-family-base: system-ui, -apple-system, 'Segoe UI', Roboto, Ubuntu, Cantarell, 'Noto Sans', sans-serif;
--ifm-heading-font-weight: 600;
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
--ifm-color-primary: #4d94ff;
--ifm-color-primary-dark: #2d81ff;
--ifm-color-primary-darker: #1d77ff;
--ifm-color-primary-darkest: #0058dc;
--ifm-color-primary-light: #6da7ff;
--ifm-color-primary-lighter: #7db1ff;
--ifm-color-primary-lightest: #aeccff;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
/* Custom colors in dark mode */
--ifm-background-color: #1a1a1a;
--ifm-background-surface-color: #242526;
--ifm-color-secondary: #4290ac;
--ifm-color-success: #2a9d47;
--ifm-color-info: #4290ac;
--ifm-color-warning: #d9a406;
--ifm-color-danger: #bd2130;
}
.hero--primary {
--ifm-hero-background-color: var(--ifm-color-primary);
--ifm-hero-text-color: var(--ifm-font-color-base-inverse);
padding: 4rem 2rem;
}
/* Add custom button spacing on homepage */
.buttons {
gap: 1rem;
display: flex;
align-items: center;
justify-content: center;
}
/* Logo styling */
.navbar__logo {
height: 2.5rem;
margin-right: 0.5rem;
}
/* Card styling for feature sections */
.card {
border-radius: 8px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
overflow: hidden;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
/* Section styling */
.section {
padding: 4rem 0;
}
.sectionAlt {
background-color: var(--ifm-color-emphasis-100);
}
/* Footer styling */
.footer {
padding: 2rem 0;
background-color: var(--ifm-color-primary-darkest);
color: var(--ifm-color-white);
}
.footer a {
color: var(--ifm-color-primary-lightest);
}
.footer a:hover {
color: var(--ifm-color-white);
text-decoration: underline;
}
.footer__title {
color: var(--ifm-color-white);
}
.footer__link-item {
opacity: 0.85;
transition: opacity 0.2s;
}
.footer__link-item:hover {
opacity: 1;
}
.footer__bottom {
border-top: 1px solid rgba(255, 255, 255, 0.2);
padding-top: 1rem;
margin-top: 1rem;
}
[data-theme='dark'] .footer {
background-color: #191919;
border-top: 1px solid #333;
}
/* Documentation styling */
.markdown h1:first-child {
--ifm-h1-font-size: 2.5rem;
margin-bottom: 1.5rem;
}
.markdown > h2 {
--ifm-h2-font-size: 2rem;
margin-top: 2.5rem;
margin-bottom: 1rem;
padding-bottom: 0.3rem;
border-bottom: 1px solid var(--ifm-color-emphasis-300);
}
.markdown > h3 {
--ifm-h3-font-size: 1.5rem;
margin-top: 2rem;
}
/* Code block styling */
pre {
border-radius: 8px;
}
/* Discord button styling */
.header-discord-link:hover {
opacity: 0.8;
}
.header-discord-link::before {
content: '';
width: 24px;
height: 24px;
display: flex;
background: url("../../static/img/discord.svg") no-repeat;
background-size: 100% 100%;
margin-right: 8px;
}
[data-theme='dark'] .header-discord-link::before {
filter: brightness(0) invert(1);
}
/* Discord badge for other elements */
.discord-badge {
display: inline-flex;
align-items: center;
margin-left: 8px;
font-size: 0.9rem;
padding: 4px 8px;
border-radius: 8px;
background-color: #5865F2;
color: white;
text-decoration: none;
transition: background-color 0.2s;
}
.discord-badge:hover {
background-color: #4752c4;
text-decoration: none;
color: white;
}
.discord-badge::before {
content: '';
width: 16px;
height: 16px;
display: inline-block;
background: url("../../static/img/discord.svg") no-repeat;
background-size: 100% 100%;
margin-right: 6px;
filter: brightness(0) invert(1);
}
+39
View File
@@ -0,0 +1,39 @@
/**
* CSS files with the .module.css suffix will be treated as CSS modules
* and scoped locally.
*/
.heroBanner {
padding: 4rem 0;
text-align: center;
position: relative;
overflow: hidden;
}
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}
.buttons {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.section {
padding: 4rem 0;
}
.sectionAlt {
background-color: var(--ifm-color-emphasis-100);
}
+182
View File
@@ -0,0 +1,182 @@
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import Layout from '@theme/Layout';
import Heading from '@theme/Heading';
import styles from './index.module.css';
function HomepageHeader() {
const {siteConfig} = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<div className="row">
<div className="col col--8 col--offset-2">
<img
src="/img/logo.svg"
alt="GoMFT Logo"
style={{width: '120px', marginBottom: '1.5rem'}}
/>
<Heading as="h1" className="hero__title">
{siteConfig.title}
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="/docs/introduction/overview">
Get Started
</Link>
<Link
className="button button--outline button--lg button--secondary"
to="https://github.com/StarFleetCPTN/GoMFT">
GitHub
</Link>
</div>
</div>
</div>
</div>
</header>
);
}
function FeatureList() {
return [
{
title: 'Easy to Use',
description: (
<>
GoMFT was designed from the ground up to be easily installed and
used to get your file transfers up and running quickly.
</>
),
},
{
title: 'Multi-Protocol Support',
description: (
<>
GoMFT leverages the power of rclone to support over 40 storage
systems including S3, SFTP, Google Drive, and more.
</>
),
},
{
title: 'Powerful Scheduling',
description: (
<>
Schedule your file transfers using familiar cron syntax for recurring transfers,
or run them on-demand with the intuitive web interface.
</>
),
},
];
}
interface FeatureProps {
title: string;
description: React.ReactElement;
}
function Feature({title, description}: FeatureProps) {
return (
<div className={clsx('col col--4')}>
<div className="text--center padding-horiz--md">
<Heading as="h3">{title}</Heading>
<p>{description}</p>
</div>
</div>
);
}
export default function Home(): React.ReactNode {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
title={`${siteConfig.title} - Modern Managed File Transfer Solution`}
description="GoMFT is a modern, open-source managed file transfer solution with multi-protocol support, scheduling capabilities, and a user-friendly web interface">
<HomepageHeader />
<main>
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList().map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
<section className={clsx(styles.section, styles.sectionAlt)}>
<div className="container">
<div className="row">
<div className="col col--6">
<Heading as="h2">Modern Web Interface</Heading>
<p>
GoMFT provides a clean, responsive web interface for managing your file transfers.
The dashboard gives you at-a-glance information about transfer status, recent jobs,
and system health.
</p>
<Link
className="button button--primary"
to="/docs/core-concepts/monitoring">
Learn More
</Link>
</div>
<div className="col col--6">
<img src="/img/dashboard.gomft.png" alt="GoMFT Dashboard" className="shadow--md" style={{borderRadius: '8px'}} />
</div>
</div>
</div>
</section>
<section className={styles.section}>
<div className="container">
<div className="row">
<div className="col col--6">
<img src="/img/transfer.config.gomft.png" alt="Transfer Configuration" className="shadow--md" style={{borderRadius: '8px'}} />
</div>
<div className="col col--6">
<Heading as="h2">Easy Deployment</Heading>
<p>
Deploy GoMFT quickly using Docker, or install it directly on your system.
The application is lightweight and can run on various platforms including
Linux, macOS, and Windows.
</p>
<Link
className="button button--primary"
to="/docs/getting-started/installation">
Installation Guide
</Link>
</div>
</div>
</div>
</section>
<section className={clsx(styles.section, styles.sectionAlt)}>
<div className="container">
<div className="text--center">
<Heading as="h2">Ready to Get Started?</Heading>
<p>
Check out our documentation to learn how to set up and use GoMFT for your file transfer needs.
</p>
<div className={styles.buttons}>
<Link
className="button button--primary button--lg"
to="/docs/introduction/overview">
Read the Docs
</Link>
<Link
className="button button--secondary button--lg"
to="https://github.com/StarFleetCPTN/GoMFT">
GitHub Repository
</Link>
</div>
</div>
</div>
</section>
</main>
</Layout>
);
}
+7
View File
@@ -0,0 +1,7 @@
---
title: Markdown page example
---
# Markdown page example
You don't need React to write simple standalone pages.
+14
View File
@@ -0,0 +1,14 @@
import React, {type ReactNode} from 'react';
import SearchBar from '@theme-original/SearchBar';
import type SearchBarType from '@theme/SearchBar';
import type {WrapperProps} from '@docusaurus/types';
type Props = WrapperProps<typeof SearchBarType>;
export default function SearchBarWrapper(props: Props): ReactNode {
return (
<>
<SearchBar {...props} />
</>
);
}
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

+41
View File
@@ -0,0 +1,41 @@
# GoMFT Documentation Images
This directory contains images used in the GoMFT documentation.
## Required Images
The following images are used in the documentation:
- `logo.svg` - The GoMFT logo for the header
- `favicon.ico` - The website favicon
- `docusaurus-social-card.jpg` - Social media preview image
- `dashboard.gomft.png` - Screenshot of the GoMFT dashboard
- `dashboard.dark.gomft.png` - Screenshot of the GoMFT dashboard in dark mode
- `transfer.config.gomft.png` - Screenshot of the transfer configuration
- `scheduled.jobs.gomft.png` - Screenshot of the scheduled jobs
- `transfer.history.gomft.png` - Screenshot of the transfer history
- `user.management.gomft.png` - Screenshot of the user management
- `role.management.gomft.png` - Screenshot of the role management
- `authentication.providers.gomft.png` - Screenshot of the authentication providers
- `notifications.gomft.png` - Screenshot of the notifications
- `notification.service.gomft.png` - Screenshot of the notification service
- `audit.logs.gomft.png` - Screenshot of the audit logs
- `file.details.gomft.png` - Screenshot of the file details
- `file.metadata.gomft.png` - Screenshot of the file metadata
- `database.tools.gomft.png` - Screenshot of the database tools
- `job.run.details.gomft.png` - Screenshot of the job run details
## Symlinks for Backward Compatibility
- `dashboard.png``dashboard.gomft.png`
- `create-transfer.png``transfer.config.gomft.png`
- `docker.png` - Placeholder for Docker-related screenshots
## Adding New Images
When adding images to this directory:
1. Use descriptive filenames
2. Optimize image size when possible
3. Use PNG for screenshots and SVG for vector graphics
4. Include alt text when referencing images in documentation
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36" fill="#5865F2">
<path d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/>
</svg>

After

Width:  |  Height:  |  Size: 769 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

+450
View File
@@ -0,0 +1,450 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="113.424mm"
height="135.52705mm"
viewBox="0 0 113.424 135.52705"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.4 (e7c3feb1, 2024-10-09)"
sodipodi:docname="gomft_golpher.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="true"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="true"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1"
inkscape:cx="182"
inkscape:cy="298"
inkscape:window-width="1512"
inkscape:window-height="831"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showborder="true" /><defs
id="defs1"><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath3542"><rect
style="fill:#0000ff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="rect3544"
width="1093.424"
height="1518.2074"
x="-1174.7097"
y="-295.40738" /></clipPath></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-48.260679,-4.7323055)"
style="display:inline"><g
style="enable-background:new"
id="g1"
transform="matrix(0.28222222,0,0,0.28222222,43.26068,-0.26769346)"
inkscape:label="golpher"><g
id="layer11"
inkscape:label="background"
style="display:inline"
transform="translate(-159.49345,-229.70978)" /><g
id="layer5"
inkscape:label="gopher-body"
style="display:inline;opacity:1"
transform="matrix(0.99955497,0,0,0.99955497,-159.32544,-229.49282)"><g
id="g4815"
transform="matrix(-0.32879267,0.17361606,0.20143296,0.28338802,93.068619,282.82497)"
style="opacity:1"><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#96d6ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -626.54672,402.3529 c 2.22767,10.86299 0.34493,21.82632 -3.86747,31.42527 -4.21252,9.59894 -10.55173,17.86115 -17.72096,24.29983 -7.1694,6.43883 -15.25476,11.10591 -24.5716,13.61353 -9.31698,2.50761 -20.94966,4.46936 -31.63903,1.98398 -10.68939,-2.48537 -18.0688,-9.22838 -24.09401,-15.89285 -6.02508,-6.66442 -12.35923,-14.47524 -22.96531,-22.06805 -10.60584,-7.59266 -20.8648,-15.59839 -25.16123,-23.3775 -4.29632,-7.77931 -7.008,-15.66934 -7.81517,-23.39095 -0.80717,-7.7215 0.35908,-14.55922 3.12288,-20.54462 2.76393,-5.98548 7.12557,-11.1208 12.7854,-15.40902 5.65998,-4.28811 12.61751,-7.73606 20.64204,-10.24271 8.02465,-2.50651 17.11262,-4.07552 27.13941,-4.41504 10.0268,-0.3395 20.06604,0.59388 29.76158,2.87504 9.69543,2.2813 19.05511,5.92037 27.47739,11.02309 8.42215,5.10286 15.89307,11.69212 21.60465,19.6287 5.71147,7.93674 13.0738,19.62846 15.30143,30.4913 z"
id="path4806"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /><path
transform="matrix(13.851095,0,0,13.851095,10133.213,-6001.611)"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m -784.21409,457.33922 c -0.56136,0.0656 -1.08141,0.1809 -1.55606,0.33615 -0.63289,0.20699 -1.18396,0.48516 -1.6349,0.82686 -0.45093,0.3417 -0.80184,0.74659 -1.02778,1.21891 -0.22595,0.47234 -0.32669,1.01119 -0.27449,1.62035 0.0522,0.60917 0.25282,1.23371 0.57968,1.84938 0.32687,0.61567 0.98957,1.25218 1.83531,1.84156 0.84574,0.58937 1.35671,1.20529 1.82543,1.72857 0.46713,0.52147 1.13451,0.85371 2.02424,0.92674 0.10253,0.008 0.12328,-0.30471 0.0344,-0.32876 -0.78083,-0.20262 -1.25826,-0.72023 -1.71877,-1.11076 -0.4254,-0.46645 -0.87231,-1.01406 -1.62104,-1.54604 -0.74871,-0.53197 -1.47289,-1.09304 -1.77689,-1.63886 -0.30398,-0.54584 -0.49685,-1.10009 -0.55469,-1.64239 -0.0579,-0.54231 0.0245,-1.0222 0.21918,-1.44322 0.19469,-0.42103 0.50198,-0.78371 0.90168,-1.08623 0.39973,-0.30252 0.89062,-0.54587 1.4577,-0.7237 0.28355,-0.0889 0.5872,-0.16119 0.90722,-0.21465 0.32002,-0.0535 0.6576,-0.0885 1.01178,-0.10163 0.70839,-0.0255 1.4163,0.0392 2.10043,0.1987 0.68412,0.15947 1.34499,0.41522 1.93838,0.77329 0.59338,0.35806 1.11885,0.81986 1.52108,1.37653 0.40222,0.55667 0.92117,1.37523 1.07925,2.13677 0.12981,0.62539 0.0734,1.25844 -0.13288,1.83379 -0.0385,0.10712 0.4977,0.29416 0.62787,-0.0111 0.24265,-0.5698 0.23445,-1.24057 0.1026,-1.8741 -0.17834,-0.85666 -0.69031,-1.76937 -1.13671,-2.40019 -0.4464,-0.6308 -1.03123,-1.15292 -1.68895,-1.55276 -0.65772,-0.39984 -1.38674,-0.68003 -2.14271,-0.85021 -0.75599,-0.17016 -1.54036,-0.23166 -2.32498,-0.19142 -0.19617,0.0101 -0.38815,0.0268 -0.57528,0.0484 z"
id="path4808"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csssccscsccscscccsccscsssscscscc" /><path
sodipodi:nodetypes="cssscsssc"
inkscape:connector-curvature="0"
id="path4810"
d="m -753.77185,413.0219 c -0.13663,-2.61847 2.18018,-4.94804 7.2193,-6.20054 7.65443,-1.90257 20.03831,1.84566 27.93811,5.67152 4.33357,2.09883 8.88981,3.89076 12.66635,7.19411 1.28185,1.12133 2.51799,2.28349 3.36855,4.40869 -1.65849,0.577 -4.10492,-0.92134 -5.87278,-2.13046 -6.96771,-4.76531 -14.69502,-8.08983 -22.67695,-9.12646 -6.71591,-0.87187 -8.86923,-3.11022 -14.75541,-2.56175 -3.72583,0.34716 -4.90626,2.13878 -7.88716,2.74489 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
sodipodi:nodetypes="sssssssss"
inkscape:connector-curvature="0"
id="path4813"
d="m -720.16989,411.68353 c 0.28532,-2.32502 0.86962,3.90377 -0.31886,5.45995 -4.46007,5.84 -8.20289,12.32072 -12.42083,18.36519 -1.37385,1.96787 -3.29463,0.0414 -2.42738,-2.09874 0.88118,-2.1739 2.06053,-3.99898 3.34915,-5.8153 1.20809,-1.70147 2.81353,-3.0576 3.88834,-4.85958 2.06619,-3.46267 2.39577,-6.62873 4.25443,-10.2393 0.63712,-1.23818 3.5225,0.42546 3.67386,-0.80905 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /></g><g
style="display:inline;enable-background:new"
id="g4710"
transform="matrix(-0.69719495,0.22290406,0.41767232,0.92198706,562.8644,-101.63567)"><path
sodipodi:nodetypes="sssssssssssssssss"
inkscape:connector-curvature="0"
id="path4706"
d="m 423.50332,581.83521 c -0.004,4.40048 -1.19837,7.58856 -3.37524,9.82844 -2.17687,2.23987 -5.33154,3.55156 -9.14619,4.44292 -3.81465,0.89135 -8.28246,1.39523 -13.05675,1.83828 -4.77428,0.44304 -9.85163,0.79076 -14.95001,1.09928 -5.09838,0.30851 -9.94541,0.34741 -14.40217,0.0862 -4.45676,-0.26122 -8.52354,-0.79908 -11.99271,-1.71189 -3.46915,-0.91282 -6.33736,-2.21356 -8.3562,-4.09288 -2.01885,-1.87935 -3.18709,-4.34475 -3.25466,-7.51083 -0.0676,-3.16607 0.9983,-5.4859 2.92534,-7.0838 1.92703,-1.5979 4.71248,-2.46394 8.09977,-2.84688 3.38729,-0.38293 7.37282,-0.28336 11.77044,-0.16051 4.39762,0.12284 9.21051,0.23456 14.33166,-0.12202 5.12115,-0.35659 10.27171,-1.47349 15.16022,-2.54099 4.88852,-1.06749 9.50395,-2.05149 13.43823,-2.27114 3.9343,-0.21967 7.17754,0.32322 9.39823,2.04598 2.22069,1.72276 3.41425,4.59936 3.41004,8.99986 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e1d6b9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
sodipodi:nodetypes="ssscsscssssssssssssssssssssccsss"
inkscape:connector-curvature="0"
id="path4708"
d="m 411.91406,568.54883 c -3.75011,-0.0271 -8.08701,0.53975 -12.76172,1.28711 -5.34251,0.85413 -11.10706,1.92059 -17.00976,2.32617 -5.9027,0.40562 -11.41103,0.38326 -16.44727,0.41406 -5.03624,0.0309 -9.6045,0.1607 -13.50781,0.85938 -3.9033,0.69867 -7.13503,1.96743 -9.4082,3.96875 -2.27316,2.00131 -3.58535,4.71676 -3.65235,8.17578 -0.067,3.45901 1.21821,6.3073 3.54297,8.58008 2.32476,2.27278 5.68789,3.9795 9.76172,5.25 4.07385,1.27051 8.85237,2.11894 14.05664,2.59765 5.20427,0.47871 10.83381,0.56134 16.70313,0.22266 5.86931,-0.33868 11.47146,-0.78653 16.60547,-1.34961 5.13399,-0.56309 9.79334,-1.22365 13.70703,-2.34375 1.48913,-0.4262 2.86677,-0.9287 4.12695,-1.51953 2.54507,-1.19325 2.05015,-6.17249 -0.0996,-4.54102 -1.99172,1.51153 -4.55969,2.50355 -7.57031,3.20703 -3.66893,0.85731 -7.96668,1.34146 -12.5586,1.76758 -4.59191,0.42612 -9.47527,0.75991 -14.3789,1.05664 -4.90363,0.29673 -9.56506,0.33523 -13.85156,0.084 -4.28652,-0.25124 -8.19851,-0.76855 -11.53516,-1.64649 -3.33664,-0.87795 -6.09539,-2.12996 -8.03711,-3.9375 -1.94173,-1.80756 -3.06587,-4.17751 -3.13086,-7.22265 -0.065,-3.04513 0.96102,-5.2776 2.81445,-6.81446 1.85342,-1.53686 4.53117,-2.36997 7.78907,-2.73828 3.2579,-0.36831 7.09262,-0.27244 11.32226,-0.1543 4.22963,0.11816 8.85767,0.22578 13.7832,-0.11718 4.92553,-0.34297 9.88026,-1.41664 14.58204,-2.44336 4.70178,-1.02671 9.13982,-1.97234 12.92382,-2.1836 0.473,-0.0264 0.93707,-0.0422 1.38868,-0.0449 1.16046,-0.007 2.25007,0.0442 3.25,0.23633 1.15313,0.22156 2.31543,-2.86146 -0.83789,-2.92773 -0.51177,-0.0108 -1.03459,-0.045 -1.57032,-0.0488 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /></g><g
style="display:inline;opacity:1"
id="g4682"
transform="matrix(-0.11933103,0.60316395,1.3605999,0.30916083,88.824519,44.52189)"><path
sodipodi:nodetypes="sssssssssssssssss"
inkscape:connector-curvature="0"
id="path4678"
d="m 767.29926,387.32674 c 11.1235,7.96555 31.77795,11.29978 44.73159,15.54502 12.95363,4.24526 18.14889,9.35948 22.12936,13.37285 3.98046,4.01338 5.94428,7.14463 4.71807,9.52723 -1.2262,2.38259 -5.54351,3.99405 -14.00119,4.81166 -8.45765,0.81761 -15.90978,0.12055 -23.02358,-1.72572 -7.11381,-1.84628 -13.80694,-4.86649 -21.70559,-8.603 -7.89866,-3.73649 -17.3272,-8.0507 -25.81115,-14.18439 -8.48395,-6.13369 -17.62324,-13.90003 -23.14238,-24.13356 -5.51915,-10.23352 -5.78201,-21.34406 -5.37146,-30.88264 0.41055,-9.53859 1.51092,-17.55377 2.71572,-23.74931 1.20482,-6.19553 2.71509,-10.67437 4.77102,-13.66952 2.05591,-2.99513 4.65165,-4.52673 7.71923,-4.52673 3.06759,0 5.70357,1.83092 7.62535,5.49926 1.9218,3.66832 3.04778,9.24444 3.28639,16.76004 0.23861,7.51561 -0.67126,17.08072 0.34029,27.19831 1.01155,10.1176 3.89485,20.79494 15.01833,28.7605 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
sodipodi:nodetypes="sssssssssssssssss"
inkscape:connector-curvature="0"
id="path4680"
d="m 760.81735,387.61463 c 8.35351,7.22933 23.40419,11.34465 36.92829,14.85447 13.52408,3.50986 21.76315,7.50998 26.41399,11.29491 4.65086,3.78492 7.04347,6.96136 6.89289,9.28045 -0.15059,2.31908 -3.07202,3.85186 -9.99413,4.53735 -6.92209,0.68549 -13.12478,-0.17957 -19.18856,-2.15841 -6.06375,-1.97886 -12.01277,-5.06603 -19.62326,-8.64782 -7.61047,-3.5818 -16.94465,-7.61787 -24.98938,-13.21535 -8.04472,-5.59749 -15.82286,-12.65396 -20.9022,-21.24583 -5.07935,-8.59186 -6.01346,-17.801 -5.99188,-25.91871 0.0216,-8.1177 0.93462,-15.14861 1.86635,-20.66954 0.93173,-5.52092 2.01706,-9.59713 3.38259,-12.30465 1.36554,-2.70753 3.03466,-4.06947 5.01979,-4.01398 1.98511,0.0555 3.57672,1.84704 4.61437,5.2751 1.03765,3.42807 1.44745,8.54444 1.4737,15.15288 0.0262,6.60845 -0.43638,14.76057 0.91317,23.27473 1.34954,8.51418 4.83074,17.27506 13.18427,24.5044 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e1d6b9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /></g><g
style="display:inline"
id="g4533-2"
transform="matrix(-0.60102903,0.32221978,0.53870829,0.77401445,526.12645,47.501077)" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.42763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 367.21812,281.2111 c 1.26906,4.8e-4 2.53948,0.0178 3.81226,0.0513 42.77724,1.12555 90.70354,5.69495 122.10388,40.54871 32.84028,36.45207 50.86245,87.73981 42.4768,134.73998 -3.70559,20.76925 -10.98111,49.47352 -17.74195,62.40674 -7.11403,13.60881 -19.80467,12.64104 -20.03271,14.6001 -0.95849,8.23388 28.65775,0.0351 45.92102,17.56348 14.06339,14.27947 18.47143,40.7184 18.81226,59.65026 0.0821,4.5609 -0.0281,9.27804 -0.3772,14.04236 -14.49094,35.53359 -47.68736,57.07915 -104.82056,72.23694 -16.35254,4.33843 -32.98332,6.84124 -49.34143,8.0127 -33.94749,-1.39556 -67.79597,-6.13242 -100.13854,-17.26685 -32.65579,-11.24226 -56.145,-40.89976 -74.77295,-73.88489 -29.47508,-52.19252 -35.755,-116.16519 -27.31567,-176.46789 7.06058,-50.45097 11.6574,-86.98057 52.22351,-116.77185 32.34621,-23.75469 69.85025,-39.47592 109.19128,-39.46106 z"
id="path4609"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssssccscscsssssc" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#96d6ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.42763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 367.42685,286.88188 c 42.99236,0.29098 91.45399,4.58065 122.97913,39.77783 29.3149,32.72949 43.70846,77.17043 40.47912,119.64477 -1.85014,24.33459 -4.2527,46.89446 -15.33809,68.52471 -7.40578,14.45044 -25.66197,16.94779 -25.75077,21.45698 -0.0598,3.03823 12.8172,2.29092 36.45996,9.33838 18.23589,5.43578 21.08736,15.45128 27.9657,34.84863 3.54426,9.99504 3.63562,21.40294 3.86353,32.07459 0.0987,4.62319 -0.16021,9.28578 -0.71778,13.93066 -15.76071,31.8161 -48.31041,51.69261 -101.98425,65.93262 -19.90398,5.28064 -40.22223,7.84987 -59.95606,8.5968 -23.42101,-1.57782 -46.67598,-5.15666 -69.29992,-11.41663 -36.53114,-10.10803 -65.44663,-39.43363 -86.5155,-75.75622 -29.60753,-51.04315 -36.18916,-113.60515 -29.37012,-173.2251 5.79548,-50.67089 11.02944,-86.89891 51.97998,-115.98999 31.47751,-22.36148 67.20785,-37.99521 105.20507,-37.73803 z"
id="path4611"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssscssccscsssss" /><path
style="opacity:1;fill:#394655;fill-opacity:1;stroke:none;stroke-width:4.6875;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.633166"
d="m 550.04547,566.15505 c -8.01527,-17.95204 -33.2969,-29.54939 -59.90815,-26.35079 -36.4344,4.37932 -107.00869,29.17307 -108.83839,27.45259 32.95965,-15.3268 80.70019,-26.25455 112.65433,-35.45314 11.18054,-3.21853 19.35455,-9.69456 24.10347,-20.91405 0,0 -4.41927,9.99274 -4.75073,10.24133 -0.33145,0.24859 -7.78922,5.96622 -7.78922,5.96622 0,0 -6.79486,3.48029 -7.29204,3.72887 -0.49719,0.2486 -4.80611,3.39744 -4.80611,3.39744 0,0 2.15446,1.57441 2.9831,1.823 0.82864,0.24859 2.98311,1.65729 4.64039,1.82301 1.65728,0.16573 7.12631,0.66292 11.93243,1.4087 4.80611,0.74577 15.08126,3.23169 17.48432,4.39179 2.40305,1.16009 7.62349,4.06034 7.87208,4.47466 0.2486,0.41432 11.71452,18.01037 11.71452,18.01037 z"
id="path4629"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscscccccsccccc" /><g
style="display:inline;opacity:1"
transform="matrix(-0.19755642,-0.64741346,0.92085299,-0.16781481,-30.330781,1045.2275)"
id="g4674"><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e1d6b9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 423.50332,581.83521 c -0.004,4.40048 -1.19837,7.58856 -3.37524,9.82844 -2.17687,2.23987 -5.33154,3.55156 -9.14619,4.44292 -3.81465,0.89135 -8.28246,1.39523 -13.05675,1.83828 -4.77428,0.44304 -9.85163,0.79076 -14.95001,1.09928 -5.09838,0.30851 -9.94541,0.34741 -14.40217,0.0862 -4.45676,-0.26122 -8.52354,-0.79908 -11.99271,-1.71189 -3.46915,-0.91282 -6.33736,-2.21356 -8.3562,-4.09288 -2.01885,-1.87935 -3.18709,-4.34475 -3.25466,-7.51083 -0.0676,-3.16607 0.9983,-5.4859 2.92534,-7.0838 1.92703,-1.5979 4.71248,-2.46394 8.09977,-2.84688 3.38729,-0.38293 7.37282,-0.28336 11.77044,-0.16051 4.39762,0.12284 9.21051,0.23456 14.33166,-0.12202 5.12115,-0.35659 10.27171,-1.47349 15.16022,-2.54099 4.88852,-1.06749 9.50395,-2.05149 13.43823,-2.27114 3.9343,-0.21967 7.17754,0.32322 9.39823,2.04598 2.22069,1.72276 3.41425,4.59936 3.41004,8.99986 z"
id="path4670"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 411.91406,568.54883 c -3.75011,-0.0271 -8.08701,0.53975 -12.76172,1.28711 -5.34251,0.85413 -11.10706,1.92059 -17.00976,2.32617 -5.9027,0.40562 -11.41103,0.38326 -16.44727,0.41406 -5.03624,0.0309 -9.6045,0.1607 -13.50781,0.85938 -3.9033,0.69867 -7.13503,1.96743 -9.4082,3.96875 -2.27316,2.00131 -3.58535,4.71676 -3.65235,8.17578 -0.067,3.45901 1.21821,6.3073 3.54297,8.58008 2.32476,2.27278 5.68789,3.9795 9.76172,5.25 4.07385,1.27051 8.85237,2.11894 14.05664,2.59765 5.20427,0.47871 10.83381,0.56134 16.70313,0.22266 5.86931,-0.33868 11.47146,-0.78653 16.60547,-1.34961 5.13399,-0.56309 9.79334,-1.22365 13.70703,-2.34375 1.48913,-0.4262 2.86677,-0.9287 4.12695,-1.51953 2.54507,-1.19325 2.05015,-6.17249 -0.0996,-4.54102 -1.99172,1.51153 -4.14364,1.68162 -7.15735,2.35061 -3.67269,0.81527 -8.18136,0.99111 -12.55008,1.3428 -4.3687,0.35167 -8.7789,1.78431 -13.31332,2.07736 -4.53444,0.29304 -8.86787,0.32801 -12.93181,0.0702 -4.06396,-0.25785 -7.85651,-0.78075 -11.12475,-1.64296 -3.26823,-0.86221 -5.99695,-2.08037 -7.8846,-3.81399 -1.88765,-1.73365 -2.92537,-3.9871 -2.97865,-6.80086 -0.0533,-2.81374 0.90176,-4.8192 2.66881,-6.10562 1.76704,-1.28641 5.61732,-0.58475 8.69196,-0.71399 3.07463,-0.12925 6.90624,-0.54484 10.78772,-0.41733 3.88147,0.12754 6.54592,-0.48119 11.04844,-1.2139 4.50252,-0.73264 9.15212,-2.3434 13.88736,-3.72101 4.73523,-1.37761 9.22461,-2.34259 13.00861,-2.55385 0.473,-0.0264 0.93707,-0.0422 1.38868,-0.0449 1.16046,-0.007 2.25007,0.0442 3.25,0.23633 1.15313,0.22156 2.31543,-2.86146 -0.83789,-2.92773 -0.51177,-0.0108 -1.03459,-0.045 -1.57032,-0.0488 z"
id="path4672"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csscsscssssssssssssssssssssccsssc" /></g><g
style="opacity:1"
transform="matrix(0.38329319,-0.18164886,0.18164886,0.38329319,415.72605,54.494616)"
id="g4804"><path
sodipodi:nodetypes="sssssssssssssssss"
inkscape:connector-curvature="0"
id="path4796"
d="m -626.57295,401.69566 c 2.24713,11.35067 0.36741,22.38948 -3.843,32.03835 -4.21053,9.64886 -10.54997,17.90531 -17.7192,24.34399 -7.1694,6.43883 -15.25457,11.1106 -24.57171,13.61082 -9.31727,2.5002 -20.94956,4.47176 -31.64526,1.82793 -10.69571,-2.64383 -18.09209,-9.81214 -24.14818,-17.25062 -6.05597,-7.43843 -12.44269,-16.56671 -23.09665,-25.35944 -10.65372,-8.79255 -20.95218,-17.78817 -25.30072,-26.87318 -4.34843,-9.08528 -7.1154,-18.36084 -7.98,-27.52156 -0.86459,-9.1606 0.24716,-17.36404 2.9617,-24.58398 2.71467,-7.22004 7.03243,-13.45488 12.66059,-18.5369 5.6283,-5.08191 12.56665,-9.01064 20.59229,-11.48936 8.02576,-2.47858 17.13537,-3.50537 27.20916,-2.66707 10.0738,0.83832 20.1809,3.47234 29.95223,7.6529 9.77122,4.18068 19.21426,9.9086 27.71179,16.89733 8.49741,6.98886 16.03465,15.24007 21.79567,24.41557 5.7609,9.17565 13.1742,22.14471 15.42129,33.49522 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#96d6ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
transform="matrix(13.851095,0,0,13.851095,10133.213,-6001.611)"
sodipodi:nodetypes="csssccscsccscscccsccscsssscscscc"
inkscape:connector-curvature="0"
id="path4798"
d="m -784.27135,455.90422 c -0.56339,0.0147 -1.08437,0.10666 -1.55902,0.26191 -0.63289,0.20699 -1.18231,0.52669 -1.63059,0.93484 -0.44828,0.40815 -0.79558,0.90361 -1.01756,1.4752 -0.22199,0.5716 -0.31844,1.21792 -0.26185,1.93717 0.0566,0.71926 0.26134,1.4471 0.59196,2.157 0.33063,0.7099 0.99621,1.41858 1.84494,2.08284 0.84872,0.66425 1.36325,1.36931 1.83382,1.93901 0.46898,0.56774 1.13678,0.9105 2.02675,0.98962 0.10256,0.009 0.12294,-0.31321 0.034,-0.33899 -0.78143,-0.21746 -1.26048,-0.77583 -1.72293,-1.21489 -0.42768,-0.5236 -0.87838,-1.16625 -1.63058,-1.78505 -0.75217,-0.61879 -1.47924,-1.25213 -1.78697,-1.89162 -0.30772,-0.63951 -0.50455,-1.29287 -0.56648,-1.9378 -0.062,-0.64492 0.0165,-1.22191 0.20772,-1.73042 0.1912,-0.50852 0.49539,-0.94884 0.89287,-1.30706 0.3975,-0.35822 0.88707,-0.63484 1.45426,-0.80994 0.2836,-0.0875 0.58767,-0.1494 0.90851,-0.1822 0.32084,-0.0328 0.65966,-0.0369 1.01552,-0.008 0.71174,0.0585 1.42446,0.24383 2.11396,0.53794 0.6895,0.29412 1.35628,0.69807 1.95502,1.19025 0.59873,0.49218 1.12894,1.07271 1.53474,1.71893 0.4058,0.64623 0.9285,1.5589 1.08808,2.35795 0.13104,0.65619 0.075,1.29927 -0.13103,1.88026 -0.0384,0.10817 0.49808,0.30362 0.62824,-0.002 0.24262,-0.57052 0.23429,-1.24452 0.10166,-1.89748 -0.17938,-0.88293 -0.69436,-1.871 -1.14416,-2.58711 -0.44981,-0.71609 -1.03943,-1.35821 -1.70275,-1.89855 -0.66333,-0.54034 -1.3987,-0.97968 -2.16052,-1.29649 -0.76184,-0.31679 -1.55154,-0.51173 -2.33984,-0.56369 -0.19709,-0.013 -0.38986,-0.0163 -0.57767,-0.0116 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
sodipodi:nodetypes="cssscsssc"
inkscape:connector-curvature="0"
id="path4800"
d="m -730.27274,382.91266 c 1.8068,-2.76405 6.31309,-3.63001 13.24575,-1.6171 10.53068,3.05761 22.43414,14.97755 28.94834,24.04709 3.57338,4.97534 7.6424,9.78266 9.64772,15.62449 0.68055,1.98294 1.27611,3.97774 0.68898,6.70435 -2.4056,-0.49416 -4.1871,-3.62313 -5.37952,-6.01329 -4.69962,-9.4202 -11.38574,-17.86492 -20.09536,-24.13889 -7.3284,-5.27852 -8.20487,-8.9719 -15.61502,-12.25742 -4.69053,-2.07967 -7.44128,-1.02076 -11.44089,-2.34923 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
sodipodi:nodetypes="sssssssss"
inkscape:connector-curvature="0"
id="path4802"
d="m -689.31909,403.49962 c 2.08771,-2.1886 -1.9021,4.5559 -4.48533,5.36905 -9.69439,3.05157 -19.01784,7.22624 -28.57811,10.64488 -3.11327,1.11257 -3.94795,-2.11026 -1.30738,-3.72982 2.68251,-1.64492 5.45711,-2.73872 8.35507,-3.75217 2.71578,-0.94874 5.64428,-1.2851 8.27731,-2.4236 5.06052,-2.18718 7.83343,-5.20599 12.75841,-7.67984 1.68866,-0.84854 3.86766,2.73608 4.97603,1.5739 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /></g></g><g
id="layer6"
inkscape:label="gopher-body-shadow"
style="opacity:0.07"
transform="translate(-22.468606,-107.81499)"><path
style="opacity:1;fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:3.53553;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 410.73438,402.67383 c -22.12212,5.91178 -47.244,11.63106 -70.61524,16.37305 -48.79037,9.89949 -67.17652,36.06247 -78.49023,54.44726 l 6.87695,-1.67969 c 36.64463,-15.30695 75.75822,-23.23183 113.48437,-35.26953 12.09814,-3.47331 21.06002,-13.5287 25.50391,-25.00976 1.18561,-2.92243 2.25783,-5.87876 3.24024,-8.86133 z"
transform="scale(0.93749999)"
id="path4829"
inkscape:connector-curvature="0" /><path
style="opacity:1;fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 176.74023,191.19336 c -12.02297,5.35584 -23.55765,11.8602 -34.44531,19.05273 -5.41851,4.11086 -12.04772,7.05917 -16.45703,12.31055 0.0894,0.61993 -0.23486,1.1597 -0.71484,1.54883 -0.66228,4.1883 -1.36755,8.37707 -2.08594,12.50781 -5.65684,32.5269 -33.941548,3.53554 -50.91211,0 -10.52665,-2.19305 -19.680537,-11.20026 -16.179688,-32.73437 -1.579179,1.23479 -3.051377,2.63841 -4.392578,4.22461 -5.278878,6.02984 -6.059769,15.29458 -3.236328,22.56836 4.226081,7.59968 10.487816,15.22544 19.425782,17.11523 7.922144,1.96176 15.28729,5.43641 22.820312,8.4375 3.386589,1.47244 7.752358,0.61137 10.76562,2.42773 -2.433965,1.64193 -6.471862,1.23181 -7.285151,4.85743 -9.479196,22.45139 -12.471269,46.96783 -15.552735,70.95117 -3.621752,29.34547 -3.810268,59.0771 -1.185546,88.50976 5.062186,45.87599 20.801047,91.1762 49.363282,127.80469 19.95688,26.39173 47.3522,48.60821 80.10937,56.24414 22.47395,5.53265 45.44736,9.51266 68.57813,10.69727 8.5266,-0.40063 17.18762,-0.50715 25.58008,-2.02539 0.38196,-2.81994 -2.61781,-5.57722 -3.4961,-8.2461 -1.44653,-3.42348 -4.19801,-6.88649 -4.1582,-10.63867 2.13967,-1.54285 1.84049,-4.80023 4.6582,-5.89648 5.55455,-3.57415 12.83988,-2.42032 18.94141,-1.75782 5.75306,0.52405 7.14734,7.19265 9.875,11.22852 2.12351,3.09028 2.41953,7.87377 5.55859,10.0625 26.17162,-6.52384 52.36044,-14.89116 75.51172,-29.04492 17.05316,-10.54934 31.72418,-25.28626 40.90821,-43.20117 -0.321,-7.86722 0.0972,-15.83004 0.0234,-23.74805 -36.4662,9.9142 -97.74588,26.5181 -128.4375,31.87695 -44.54772,7.77818 -96.87505,9.19053 -150.61515,-30.40744 -65.69966,-48.41028 -44.54795,-229.80948 -35.35555,-265.16482 4.79814,-18.45438 17.9071,-38.64402 42.39062,-59.56055 z"
transform="scale(0.93749999)"
id="path4834"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccssccccccccccccccccccccccsssc" /><path
style="opacity:1;fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:4.6875;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 221.25,457.42331 c 0,0 15,15.23437 22.03125,18.04687 7.03125,2.8125 20.85937,11.01563 28.125,14.76563 7.26562,3.75 7.73437,10.07812 22.96875,4.21875 15.23437,-5.85938 20.39062,-10.07813 30.9375,-11.71875 10.54687,-1.64063 18.04687,-0.9375 25.07812,-3.98438 7.03125,-3.04687 23.90625,-10.78125 28.59375,-13.35937 4.6875,-2.57813 9.60938,-2.57813 13.82813,-3.98438 4.21875,-1.40625 17.10937,-0.23437 19.45312,-3.75 2.34375,-3.51562 3.75,-3.98437 3.04688,-6.5625 -0.70313,-2.57812 -7.03125,-15 -15,-16.875 -7.96875,-1.875 -14.76563,-2.34375 -36.5625,-1.875 -21.79688,0.46875 -18.75,-1.17187 -39.14063,4.45313 -20.39062,5.625 -14.76562,10.78125 -37.26562,12.89062 -22.5,2.10938 -17.10938,2.10938 -29.53125,1.64063 -12.42188,-0.46875 -11.71875,-0.23438 -19.6875,-1.64063 -7.96875,-1.40625 -16.875,7.73438 -16.875,7.73438 z"
id="path4842"
inkscape:connector-curvature="0" /><path
style="opacity:1;fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:4.6875;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 364.92187,465.15768 c 15,5.85938 16.875,39.60938 16.875,39.60938 0,0 3.98438,3.28125 4.21875,-0.70313 5.3692,-7.3069 -8.34035,-45.03528 -13.82812,-41.48437 z"
id="path4844"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;opacity:1;fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:0.883883;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;enable-background:new"
d="m 280.10156,140.0293 c -3.31241,1.49194 -6.45666,3.36696 -9.3457,5.52929 -5.80006,4.43544 -10.87913,10.55536 -12.1543,17.92774 -0.29285,2.25732 -0.37829,4.57376 -0.32617,6.82812 0.54553,0.71731 1.76636,0.2809 2.5957,0.47852 3.60567,0.16435 7.21143,0.36527 10.8125,0.60937 -3.09385,-7.05751 -2.40538,-18.24537 8.41797,-31.37304 z"
transform="scale(0.93749999)"
id="path4846"
inkscape:connector-curvature="0" /></g><g
id="layer2"
inkscape:label="gopher-face"
style="display:inline"
transform="translate(-159.49345,-229.70978)"><g
transform="matrix(-0.70545801,0,0,0.70545801,653.3373,199.47893)"
id="g4639"><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 547.42756,318.16456 c -0.44046,14.77191 -4.12869,29.02667 -10.38967,42.25266 -6.26099,13.22599 -15.09198,25.42687 -25.80466,35.99686 -10.71268,10.57 -23.30432,19.50822 -37.11826,26.08983 -13.81394,6.58161 -28.85103,10.80263 -44.50193,11.8618 -15.65091,1.05917 -30.4406,-1.15844 -43.81781,-6.16756 -13.37721,-5.00911 -25.3405,-12.8075 -35.30087,-22.80416 -9.96037,-9.99666 -17.91599,-22.19037 -23.26581,-35.90798 -5.34983,-13.71761 -8.0915,-28.95913 -7.64195,-44.98105 0.44955,-16.02192 4.04447,-31.2937 10.1422,-45.07896 6.09773,-13.78526 14.69591,-26.08175 25.16951,-36.25747 10.4736,-10.17571 22.82245,-18.23043 36.46168,-23.66123 13.63924,-5.4308 28.57214,-8.24285 44.22923,-8.02541 15.6571,0.21745 30.56095,3.42714 44.11009,8.94154 13.54914,5.5144 25.7404,13.33722 35.92568,22.91495 10.18529,9.57774 18.36233,20.91345 23.87736,33.53282 5.51504,12.61936 8.36566,26.52144 7.92521,41.29336 z"
id="path4631"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 539.72249,314.79002 c 10e-4,13.89984 -3.01572,27.53808 -8.51346,40.35257 -5.49774,12.81449 -13.48047,24.80543 -23.37659,35.2527 -9.89612,10.44726 -21.70519,19.34133 -34.78531,25.87862 -13.08011,6.53727 -27.4256,10.71236 -42.3773,11.7667 -14.9517,1.05435 -29.09103,-1.11258 -41.85904,-5.93108 -12.76803,-4.81852 -24.16883,-12.28715 -33.66552,-21.79076 -9.49671,-9.50362 -17.08979,-21.04298 -22.23241,-33.95465 -5.14261,-12.91166 -7.83328,-27.19561 -7.52333,-42.13595 0.30995,-14.94034 3.58995,-29.10832 9.22975,-41.85842 5.63981,-12.7501 13.63743,-24.08168 23.39638,-33.47108 9.75897,-9.38941 21.27795,-16.83842 34.00359,-21.94183 12.72563,-5.10342 26.66067,-7.86812 41.28534,-7.94317 14.62467,-0.0751 28.55938,2.53224 41.26083,7.24431 12.70145,4.71207 24.16709,11.5339 33.81555,20.03646 9.64847,8.50257 17.47884,18.68937 22.90117,30.21241 5.42232,11.52304 8.43889,24.38332 8.44035,38.28317 z"
id="path4633"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /><circle
r="30.809652"
cy="314.25491"
cx="420.48679"
id="circle4635"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394455;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><circle
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="circle4637"
cx="406.84973"
cy="300.11276"
r="15.152287" /></g><g
id="g4651"
transform="matrix(-0.3718816,-0.33035833,-0.33035833,0.3718816,807.54151,424.47556)"><path
sodipodi:nodetypes="sssssssssssssssss"
inkscape:connector-curvature="0"
id="path4643"
d="m 549.05152,326.95134 c -3.75547,13.70752 -9.94485,27.49753 -18.134,40.75742 -8.18917,13.2599 -18.55963,25.88871 -30.48613,36.73483 -11.9265,10.84612 -25.26726,19.91416 -38.40631,26.7046 -13.13906,6.79044 -26.00962,11.35394 -38.37684,13.00513 -12.36722,1.6512 -23.25032,0.18545 -33.06847,-4.02278 -9.81817,-4.20823 -22.90634,-9.21469 -29.99096,-18.16657 -7.08461,-8.95188 -12.84054,-20.18257 -16.5035,-33.03389 -3.66297,-12.85133 -5.229,-27.32914 -3.92417,-42.72858 1.30484,-15.39944 5.36688,-30.24976 11.81788,-43.75488 6.45101,-13.5051 15.29008,-25.65823 26.00811,-35.78271 10.71803,-10.12447 28.44246,-20.29305 42.24879,-25.86698 13.80633,-5.57394 28.83304,-8.62768 44.20973,-8.80364 15.3767,-0.17594 29.62737,2.52591 41.94358,7.37479 12.31622,4.84887 22.69735,11.85058 30.35956,20.34718 7.66222,8.49661 12.72593,18.56023 14.82358,29.82149 2.09769,11.26125 1.23461,23.70707 -2.52085,37.41459 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
sodipodi:nodetypes="sssssssssssssssss"
inkscape:connector-curvature="0"
id="path4645"
d="m 543.48686,325.96521 c -3.05527,12.95406 -8.32379,26.18736 -15.65713,38.96025 -7.33335,12.77289 -16.92422,24.96643 -28.32938,35.27691 -11.40514,10.31051 -24.49416,18.73032 -37.45951,24.88997 -12.96533,6.15964 -25.70084,10.13776 -37.71064,11.47666 -12.00982,1.33889 -22.34344,-0.13174 -31.49437,-4.07588 -9.15093,-3.94412 -22.12504,-8.81495 -28.38237,-17.0256 -6.25732,-8.21068 -11.24381,-18.53447 -14.30417,-30.37519 -3.06035,-11.84072 -4.18965,-25.20221 -2.68634,-39.42576 1.5033,-14.22354 5.50837,-27.94818 11.67956,-40.43838 6.17119,-12.4902 14.50792,-23.74111 24.54768,-33.13895 10.03978,-9.39782 26.99021,-19.0621 39.83566,-24.2929 12.84546,-5.2308 26.78412,-8.15811 41.0009,-8.45853 14.21678,-0.30038 27.34319,2.03758 38.64284,6.33106 11.29965,4.29349 20.72984,10.51935 27.81498,18.21491 7.08513,7.69557 11.8105,16.84485 13.92296,27.20306 2.11247,10.35821 1.63459,21.92432 -1.42067,34.87837 z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><circle
transform="rotate(9.4590451)"
r="27.721321"
cy="221.94495"
cx="451.74091"
id="circle4647"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394455;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><circle
transform="rotate(9.4590451)"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="circle4649"
cx="444.28159"
cy="208.59291"
r="13.633434" /></g></g><g
id="layer8"
inkscape:label="gopher-eye-shadow"
style="opacity:0.07"
transform="translate(-22.468606,-107.81499)"><path
style="opacity:1;fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 183.98633,257.10938 c -12.96514,6.80368 -24.09238,16.98928 -31.2461,29.85742 -6.62306,11.80983 -9.18947,25.58787 -7.96289,39.02734 1.67308,22.69639 14.45708,43.56009 31.54688,58.10156 14.06811,11.68944 31.68858,19.74781 50.07226,20.84571 11.72752,0.49232 23.74714,-0.51041 34.5586,-5.42579 7.00377,-3.01395 13.43915,-7.17995 19.12109,-12.20898 -12.36895,1.55403 -17.4885,4.99626 -41.57617,5.11133 -34.01431,0.16249 -53,-11.5 -68.5,-36.5 -14.1749,-22.86275 -23.28438,-60.80338 13.98633,-98.80859 z"
transform="scale(0.93749999)"
id="path4853"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccssc" /><path
style="opacity:1;fill:#1e1e1e;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 407.00195,240.87891 c -9.28173,2.40304 -16.98081,9.77947 -21.58398,18.09375 -9.07687,16.02983 -11.91205,35.42287 -8.52539,53.46875 3.18065,14.4141 9.49376,28.957 20.97265,38.67382 5.72719,4.40424 12.92201,6.42783 19.83399,8.13477 6.81141,1.14046 13.43258,-1.454 19.35351,-4.83008 -10.63686,0.15673 -18.09098,-0.62412 -29.80273,-7.00195 -16.87155,-9.18769 -20.86545,-23.47661 -24.25,-43.5 -2.91982,-17.27395 -3.79826,-39.70251 24.00195,-63.03906 z"
transform="scale(0.93749999)"
id="path4855"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccssc" /></g><g
id="layer7"
inkscape:label="gopher-mouth"
style="display:inline"
transform="translate(-159.49345,-229.70978)"><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#1e1e1e;fill-opacity:0.0854271;fill-rule:nonzero;stroke:none;stroke-width:11.1413;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 479.16003,446.53263 c -0.5609,0.0108 -1.13139,0.0418 -1.70837,0.0934 -2.30796,0.20633 -4.51646,0.72546 -6.51307,1.48133 -1.9966,0.75587 -3.78067,1.74769 -5.22583,2.89856 -1.0355,0.82461 -1.88701,1.73417 -2.51953,2.69165 -0.49936,0.12274 -1.0048,0.23296 -1.49781,0.36987 -3.81399,1.05919 -7.40798,2.54289 -10.40404,4.35608 -2.99605,1.81321 -5.4585,3.90209 -6.89576,6.26037 -1.4722,2.41563 -1.97188,5.13866 -1.80359,7.29493 0.19753,2.5307 1.75758,4.81955 3.97339,6.88111 2.21579,2.06154 5.27574,3.88827 8.8202,5.38513 1.41204,0.59632 2.90966,1.1203 4.4403,1.59484 l -0.83679,5.84107 -1.56738,7.92297 c -0.28234,1.42686 0.0936,2.6844 0.78552,3.59985 0.69199,0.91542 1.75347,1.43692 3.00476,1.46668 l 4.17114,0.10071 8.25256,-0.19226 c 1.58268,-0.0369 3.05271,-0.65206 4.13086,-1.59668 1.07816,-0.94464 1.71703,-2.22901 1.84571,-3.63098 l 0.72143,-7.86255 0.29663,-3.98255 c 3.44589,-0.52696 6.56272,-1.40104 9.31274,-2.44995 3.13519,-1.19582 5.76942,-2.61386 7.84425,-4.18763 2.07486,-1.57375 3.60911,-3.3186 4.57763,-5.26427 0.96853,-1.94567 1.36942,-4.09866 1.01807,-6.41968 -0.35134,-2.32102 -1.43875,-4.58369 -3.11829,-6.66321 -1.39778,-1.73064 -3.21452,-3.31999 -5.30822,-4.7168 0.0111,-0.55256 -0.0197,-1.11781 -0.13001,-1.69922 -0.26781,-1.4117 -0.89157,-2.76339 -1.83655,-3.9862 -0.94497,-1.22282 -2.2106,-2.31507 -3.73901,-3.20068 -1.52841,-0.88563 -3.32124,-1.56509 -5.31189,-1.96839 -1.49298,-0.30248 -3.09635,-0.44985 -4.77905,-0.41748 z"
id="path4863"
inkscape:connector-curvature="0" /><g
id="g4823"
transform="translate(12.595339,-3.9774756)"><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:11.1413;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 467.31675,478.77402 -7.09437,0.0922 -4.13468,-0.0915 c -1.31882,-0.0292 -2.49364,0.59671 -3.34977,1.51944 -0.85615,0.92274 -1.27744,2.20064 -1.47679,3.59515 l -1.12865,7.8943 -1.5677,7.92258 c -0.28234,1.42686 0.0937,2.68467 0.78566,3.60012 0.69199,0.91542 1.75323,1.43698 3.00452,1.46674 l 4.17197,0.0993 8.25189,-0.19228 c 1.58268,-0.0369 3.05287,-0.65192 4.13103,-1.59654 1.07815,-0.94464 1.7158,-2.22919 1.84447,-3.63117 l 0.72151,-7.86154 0.58517,-7.8491 c 0.10417,-1.3971 -0.52004,-2.64858 -1.39674,-3.54475 -0.8767,-0.89618 -2.06937,-1.43077 -3.34749,-1.42293 z"
id="path4686"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scssscssscssscsss" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:11.1413;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 466.02149,481.16374 -5.78995,0.0778 -2.75744,-0.11307 c -1.04748,-0.043 -2.01463,0.4856 -2.74214,1.24096 -0.72751,0.75535 -1.15228,1.80234 -1.35005,2.94507 l -1.11703,6.45444 -1.39816,6.47122 c -0.24964,1.15537 0.002,2.19546 0.54523,2.94311 0.5435,0.74764 1.41108,1.15214 2.44988,1.1934 l 2.83204,0.11253 6.55718,-0.1421 c 1.24167,-0.027 2.42344,-0.526 3.31255,-1.29718 0.88911,-0.77118 1.45844,-1.82149 1.60367,-2.96928 l 0.81341,-6.4286 0.70226,-6.42074 c 0.12544,-1.14351 -0.31817,-2.1697 -0.99356,-2.90365 -0.67536,-0.73395 -1.62282,-1.178 -2.66787,-1.16394 z"
id="path4688"
inkscape:connector-curvature="0"
sodipodi:nodetypes="scssscssscssscsss" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:11.1413;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 433.73526,472.08025 c 0.19752,2.5307 1.75649,4.82026 3.9723,6.88181 2.21579,2.06155 5.27599,3.88893 8.82045,5.38579 3.54446,1.49687 7.54259,2.64799 11.59243,3.26302 4.04985,0.61505 8.15288,0.68338 12.18571,0.19715 4.03281,-0.48626 7.64449,-1.45413 10.77968,-2.64995 3.13518,-1.19582 5.76946,-2.61453 7.84429,-4.18829 2.07486,-1.57376 3.60891,-3.31701 4.57744,-5.26269 0.96853,-1.94567 1.37034,-4.09954 1.01899,-6.42056 -0.35134,-2.32102 -1.4393,-4.58444 -3.11884,-6.66396 -1.67955,-2.07951 -3.93835,-3.97272 -6.59166,-5.54818 -2.6533,-1.57546 -5.69659,-2.83225 -9.05614,-3.65611 -3.35955,-0.82385 -7.03889,-1.21547 -11.06436,-1.08264 -4.02547,0.13285 -8.04246,0.77372 -11.85647,1.83293 -3.814,1.05919 -7.40852,2.54378 -10.40458,4.35697 -2.99604,1.81321 -5.45804,3.90231 -6.89529,6.26059 -1.4722,2.41563 -1.97224,5.13785 -1.80395,7.29412 z"
id="path4690"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e1d0cb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:11.1413;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 442.25761,471.51199 c 0.34559,2.01022 1.52164,3.88762 3.32749,5.56973 1.80585,1.68211 4.23932,3.17214 7.00457,4.36112 2.76524,1.18899 5.84856,2.06805 8.99234,2.52986 3.14378,0.46181 6.35142,0.50432 9.50541,0.11936 3.15398,-0.38496 5.97075,-1.14729 8.41503,-2.12187 2.44428,-0.97459 4.50648,-2.15972 6.12437,-3.48208 1.61791,-1.32236 2.79548,-2.78732 3.48967,-4.38292 0.69419,-1.59559 0.90742,-3.32616 0.54576,-5.15905 -0.36166,-1.8329 -1.26917,-3.59361 -2.60863,-5.20009 -1.33945,-1.60649 -3.10784,-3.05657 -5.19076,-4.25685 -2.08293,-1.20029 -4.4781,-2.15007 -7.11901,-2.76427 -2.6409,-0.61421 -5.52795,-0.89311 -8.65369,-0.76365 -3.12573,0.12948 -6.20924,0.65323 -9.12183,1.4947 -2.91261,0.84148 -5.65005,2.00273 -7.96189,3.4111 -2.31186,1.40839 -4.18867,3.06443 -5.38415,4.87182 -1.19548,1.8074 -1.71029,3.76288 -1.36468,5.77309 z"
id="path4692"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:11.1413;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 453.44155,459.24387 c 0.50394,1.4405 1.59973,2.71976 3.11582,3.79941 1.51609,1.07966 3.44645,1.96175 5.54093,2.63816 2.09447,0.67641 4.34429,1.14922 6.54588,1.40092 2.20159,0.25168 4.3549,0.28101 6.37262,0.0579 2.01772,-0.22314 3.7207,-0.67675 5.162,-1.30838 1.44132,-0.63166 2.6208,-1.44105 3.55014,-2.39383 0.92933,-0.95279 1.60959,-2.05056 2.00449,-3.26657 0.39491,-1.21603 0.50374,-2.55168 0.23592,-3.96339 -0.26781,-1.41171 -0.89241,-2.76478 -1.83739,-3.98759 -0.94498,-1.22282 -2.20943,-2.31451 -3.73784,-3.20012 -1.52841,-0.88562 -3.32073,-1.5647 -5.31138,-1.968 -1.99064,-0.40331 -4.17987,-0.53049 -6.48783,-0.32418 -2.30795,0.20632 -4.51621,0.7257 -6.51282,1.48157 -1.9966,0.75587 -3.78172,1.74809 -5.22688,2.89895 -1.44517,1.15085 -2.55022,2.46103 -3.16907,3.84701 -0.61885,1.38597 -0.74853,2.84764 -0.24459,4.28815 z"
id="path4694"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /></g></g><g
id="layer3"
inkscape:label="gopher-eye-lashes"
style="display:inline"
transform="translate(-159.49345,-229.70978)" /><g
id="g2"
transform="matrix(0.29908034,-0.07349009,0.08149446,0.24234368,225.1279,272.80177)"
inkscape:label="folder"
style="display:inline"><path
id="SVGCleanerId_0"
style="fill:#ffc36e"
d="M 183.295,123.586 H 55.05 c -6.687,0 -12.801,-3.778 -15.791,-9.76 L 26.483,88.276 39.259,62.726 c 2.99,-5.982 9.103,-9.76 15.791,-9.76 h 128.246 c 6.687,0 12.801,3.778 15.791,9.76 l 12.775,25.55 -12.776,25.55 c -2.99,5.982 -9.103,9.76 -15.791,9.76 z" /><g
id="g1-9">
<path
id="SVGCleanerId_0_1_"
style="fill:#ffc36e"
d="M 183.295,123.586 H 55.05 c -6.687,0 -12.801,-3.778 -15.791,-9.76 L 26.483,88.276 39.259,62.726 c 2.99,-5.982 9.103,-9.76 15.791,-9.76 h 128.246 c 6.687,0 12.801,3.778 15.791,9.76 l 12.775,25.55 -12.776,25.55 c -2.99,5.982 -9.103,9.76 -15.791,9.76 z" />
</g><path
style="fill:#eff2fa"
d="M 485.517,70.621 H 26.483 c -4.875,0 -8.828,3.953 -8.828,8.828 v 44.138 h 476.69 V 79.448 c 0,-4.875 -3.953,-8.827 -8.828,-8.827 z"
id="path1" /><rect
x="17.655001"
y="105.931"
style="fill:#e1e6f2"
width="476.69"
height="17.655001"
id="rect1" /><path
style="fill:#ffd782"
d="M 494.345,88.276 H 217.318 c -3.343,0 -6.4,1.889 -7.895,4.879 l -10.336,20.671 c -2.99,5.982 -9.105,9.76 -15.791,9.76 H 55.05 c -6.687,0 -12.801,-3.778 -15.791,-9.76 L 28.922,93.155 C 27.427,90.165 24.37,88.276 21.027,88.276 H 17.655 C 7.904,88.276 0,96.18 0,105.931 v 335.448 c 0,9.751 7.904,17.655 17.655,17.655 h 476.69 c 9.751,0 17.655,-7.904 17.655,-17.655 V 105.931 c 0,-9.751 -7.904,-17.655 -17.655,-17.655 z"
id="path2" /><path
style="fill:#ffc36e"
d="M 485.517,441.379 H 26.483 c -4.875,0 -8.828,-3.953 -8.828,-8.828 v 0 c 0,-4.875 3.953,-8.828 8.828,-8.828 h 459.034 c 4.875,0 8.828,3.953 8.828,8.828 v 0 c 0,4.876 -3.953,8.828 -8.828,8.828 z"
id="path3" /><path
style="fill:#eff2fa"
d="m 326.621,220.69 h 132.414 c 4.875,0 8.828,-3.953 8.828,-8.828 v -70.621 c 0,-4.875 -3.953,-8.828 -8.828,-8.828 H 326.621 c -4.875,0 -8.828,3.953 -8.828,8.828 v 70.621 c 0,4.875 3.953,8.828 8.828,8.828 z"
id="path4" /><path
style="fill:#c7cfe2"
d="m 441.379,167.724 h -97.103 c -4.875,0 -8.828,-3.953 -8.828,-8.828 v 0 c 0,-4.875 3.953,-8.828 8.828,-8.828 h 97.103 c 4.875,0 8.828,3.953 8.828,8.828 v 0 c 0,4.876 -3.953,8.828 -8.828,8.828 z"
id="path5" /><path
style="fill:#d7deed"
d="m 441.379,203.034 h -97.103 c -4.875,0 -8.828,-3.953 -8.828,-8.828 v 0 c 0,-4.875 3.953,-8.828 8.828,-8.828 h 97.103 c 4.875,0 8.828,3.953 8.828,8.828 v 0 c 0,4.876 -3.953,8.828 -8.828,8.828 z"
id="path6" /></g><g
id="layer12"
inkscape:label="gopher-hands"
style="display:inline"
transform="translate(-159.49345,-229.70978)"><g
transform="matrix(-0.73022337,-0.0504068,0.04754695,1.0110636,636.13477,-6.0140033)"
id="g4702"><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e1d6b9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 423.50332,581.83521 c -0.004,4.40048 -1.19837,7.58856 -3.37524,9.82844 -2.17687,2.23987 -5.33154,3.55156 -9.14619,4.44292 -3.81465,0.89135 -8.28246,1.39523 -13.05675,1.83828 -4.77428,0.44304 -9.85163,0.79076 -14.95001,1.09928 -5.09838,0.30851 -9.94541,0.34741 -14.40217,0.0862 -4.45676,-0.26122 -8.52354,-0.79908 -11.99271,-1.71189 -3.46915,-0.91282 -6.33736,-2.21356 -8.3562,-4.09288 -2.01885,-1.87935 -3.18709,-4.34475 -3.25466,-7.51083 -0.0676,-3.16607 0.9983,-5.4859 2.92534,-7.0838 1.92703,-1.5979 4.71248,-2.46394 8.09977,-2.84688 3.38729,-0.38293 7.37282,-0.28336 11.77044,-0.16051 4.39762,0.12284 9.21051,0.23456 14.33166,-0.12202 5.12115,-0.35659 10.27171,-1.47349 15.16022,-2.54099 4.88852,-1.06749 9.50395,-2.05149 13.43823,-2.27114 3.9343,-0.21967 7.17754,0.32322 9.39823,2.04598 2.22069,1.72276 3.41425,4.59936 3.41004,8.99986 z"
id="path4698"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssssssssssssss" /><path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 411.91406,568.54883 c -3.75011,-0.0271 -8.08701,0.53975 -12.76172,1.28711 -5.34251,0.85413 -11.10706,1.92059 -17.00976,2.32617 -5.9027,0.40562 -11.41103,0.38326 -16.44727,0.41406 -5.03624,0.0309 -9.6045,0.1607 -13.50781,0.85938 -3.9033,0.69867 -7.13503,1.96743 -9.4082,3.96875 -2.27316,2.00131 -3.58535,4.71676 -3.65235,8.17578 -0.067,3.45901 1.21821,6.3073 3.54297,8.58008 2.32476,2.27278 5.68789,3.9795 9.76172,5.25 4.07385,1.27051 8.85237,2.11894 14.05664,2.59765 5.20427,0.47871 10.83381,0.56134 16.70313,0.22266 5.86931,-0.33868 11.47146,-0.78653 16.60547,-1.34961 5.13399,-0.56309 9.79334,-1.22365 13.70703,-2.34375 1.48913,-0.4262 2.86677,-0.9287 4.12695,-1.51953 2.54507,-1.19325 2.05015,-6.17249 -0.0996,-4.54102 -1.99172,1.51153 -4.55969,2.50355 -7.57031,3.20703 -3.66893,0.85731 -7.96668,1.34146 -12.5586,1.76758 -4.59191,0.42612 -9.47527,0.75991 -14.3789,1.05664 -4.90363,0.29673 -9.56506,0.33523 -13.85156,0.084 -4.28652,-0.25124 -8.19851,-0.76855 -11.53516,-1.64649 -3.33664,-0.87795 -6.09539,-2.12996 -8.03711,-3.9375 -1.94173,-1.80756 -3.06587,-4.17751 -3.13086,-7.22265 -0.065,-3.04513 0.96102,-5.2776 2.81445,-6.81446 1.85342,-1.53686 4.53117,-2.36997 7.78907,-2.73828 3.2579,-0.36831 7.09262,-0.27244 11.32226,-0.1543 4.22963,0.11816 8.85767,0.22578 13.7832,-0.11718 4.92553,-0.34297 9.88026,-1.41664 14.58204,-2.44336 4.70178,-1.02671 9.13982,-1.97234 12.92382,-2.1836 0.473,-0.0264 0.93707,-0.0422 1.38868,-0.0449 1.16046,-0.007 2.25007,0.0442 3.25,0.23633 1.15313,0.22156 2.31543,-2.86146 -0.83789,-2.92773 -0.51177,-0.0108 -1.03459,-0.045 -1.57032,-0.0488 z"
id="path4700"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssscsscssssssssssssssssssssccsss" /></g></g><g
id="layer4"
inkscape:label="palette"
style="display:none"
transform="translate(-159.49345,-229.70978)"><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394655;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4162"
width="40.789474"
height="40.789474"
x="779.60529"
y="21.967466" /><rect
y="21.967466"
x="824.60529"
height="40.789474"
width="40.789474"
id="rect4170"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#bce8ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4208"
width="40.789474"
height="40.789474"
x="779.60529"
y="86.967468" /><rect
y="-127.75694"
x="824.60529"
height="40.789474"
width="40.789474"
id="rect4223"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#abccd9;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
transform="scale(1,-1)" /><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c3b0cb;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4227"
width="40.789474"
height="40.789474"
x="779.60529"
y="131.96747" /><rect
y="131.96747"
x="824.60529"
height="40.789474"
width="40.789474"
id="rect4231"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#e1d0cb;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f5c3d2;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4233"
width="40.789474"
height="40.789474"
x="869.60529"
y="131.96747" /><rect
y="176.96747"
x="779.60529"
height="40.789474"
width="40.789474"
id="rect4248"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#cec4ad;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><rect
transform="scale(1,-1)"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#96d6ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4263"
width="40.789474"
height="40.789474"
x="869.60529"
y="-127.75694" /><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f2f2ce;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4267"
width="40.789474"
height="40.789474"
x="824.60529"
y="176.96747" /><rect
y="-327.75693"
x="779.60529"
height="40.789474"
width="40.789474"
id="rect4280"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#24b8eb;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
transform="scale(1,-1)" /><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#8aa9ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4284"
width="40.789474"
height="40.789474"
x="824.60529"
y="286.96747" /><rect
y="331.96747"
x="779.60529"
height="40.789474"
width="40.789474"
id="rect4297"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d4edf1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#394d54;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4301"
width="40.789474"
height="40.789474"
x="779.60529"
y="241.96747" /><rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d6e2ff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:9.21053;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4303"
width="40.789474"
height="40.789474"
x="824.60529"
y="331.96747" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

+1
View File
@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

+171
View File
@@ -0,0 +1,171 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1088" height="687.962" viewBox="0 0 1088 687.962">
<title>Easy to Use</title>
<g id="Group_12" data-name="Group 12" transform="translate(-57 -56)">
<g id="Group_11" data-name="Group 11" transform="translate(57 56)">
<path id="Path_83" data-name="Path 83" d="M1017.81,560.461c-5.27,45.15-16.22,81.4-31.25,110.31-20,38.52-54.21,54.04-84.77,70.28a193.275,193.275,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.282,657.282,0,0,0-104.09-13.16q-14.97-.675-29.97-.67c-15.42.02-293.07,5.29-360.67-131.57-16.69-33.76-28.13-75-32.24-125.27-11.63-142.12,52.29-235.46,134.74-296.47,155.97-115.41,369.76-110.57,523.43,7.88C941.15,276.621,1036.99,396.031,1017.81,560.461Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_84" data-name="Path 84" d="M986.56,670.771c-20,38.52-47.21,64.04-77.77,80.28a193.272,193.272,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.3,657.3,0,0,0-104.09-13.16q-14.97-.675-29.97-.67-23.13.03-46.25,1.72c-100.17,7.36-253.82-6.43-321.42-143.29L382,283.981,444.95,445.6l20.09,51.59,55.37-75.98L549,381.981l130.2,149.27,36.8-81.27L970.78,657.9l14.21,11.59Z" transform="translate(-56 -106.019)" fill="#f2f2f2"/>
<path id="Path_85" data-name="Path 85" d="M302,282.962l26-57,36,83-31-60Z" opacity="0.1"/>
<path id="Path_86" data-name="Path 86" d="M610.5,753.821q-14.97-.675-29.97-.67L465.04,497.191Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<path id="Path_87" data-name="Path 87" d="M464.411,315.191,493,292.962l130,150-132-128Z" opacity="0.1"/>
<path id="Path_88" data-name="Path 88" d="M908.79,751.051a193.265,193.265,0,0,1-27.46,11.94L679.2,531.251Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3" cy="3" r="3" transform="translate(479 98.962)" fill="#f2f2f2"/>
<circle id="Ellipse_12" data-name="Ellipse 12" cx="3" cy="3" r="3" transform="translate(396 201.962)" fill="#f2f2f2"/>
<circle id="Ellipse_13" data-name="Ellipse 13" cx="2" cy="2" r="2" transform="translate(600 220.962)" fill="#f2f2f2"/>
<circle id="Ellipse_14" data-name="Ellipse 14" cx="2" cy="2" r="2" transform="translate(180 265.962)" fill="#f2f2f2"/>
<circle id="Ellipse_15" data-name="Ellipse 15" cx="2" cy="2" r="2" transform="translate(612 96.962)" fill="#f2f2f2"/>
<circle id="Ellipse_16" data-name="Ellipse 16" cx="2" cy="2" r="2" transform="translate(736 192.962)" fill="#f2f2f2"/>
<circle id="Ellipse_17" data-name="Ellipse 17" cx="2" cy="2" r="2" transform="translate(858 344.962)" fill="#f2f2f2"/>
<path id="Path_89" data-name="Path 89" d="M306,121.222h-2.76v-2.76h-1.48v2.76H299V122.7h2.76v2.759h1.48V122.7H306Z" fill="#f2f2f2"/>
<path id="Path_90" data-name="Path 90" d="M848,424.222h-2.76v-2.76h-1.48v2.76H841V425.7h2.76v2.759h1.48V425.7H848Z" fill="#f2f2f2"/>
<path id="Path_91" data-name="Path 91" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_92" data-name="Path 92" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<ellipse id="Ellipse_18" data-name="Ellipse 18" cx="544" cy="30" rx="544" ry="30" transform="translate(0 583.962)" fill="#3f3d56"/>
<path id="Path_93" data-name="Path 93" d="M624,677.981c0,33.137-14.775,24-33,24s-33,9.137-33-24,33-96,33-96S624,644.844,624,677.981Z" transform="translate(-56 -106.019)" fill="#ff6584"/>
<path id="Path_94" data-name="Path 94" d="M606,690.66c0,15.062-6.716,10.909-15,10.909s-15,4.153-15-10.909,15-43.636,15-43.636S606,675.6,606,690.66Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<rect id="Rectangle_97" data-name="Rectangle 97" width="92" height="18" rx="9" transform="translate(489 604.962)" fill="#2f2e41"/>
<rect id="Rectangle_98" data-name="Rectangle 98" width="92" height="18" rx="9" transform="translate(489 586.962)" fill="#2f2e41"/>
<path id="Path_95" data-name="Path 95" d="M193,596.547c0,55.343,34.719,100.126,77.626,100.126" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_96" data-name="Path 96" d="M270.626,696.673c0-55.965,38.745-101.251,86.626-101.251" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_97" data-name="Path 97" d="M221.125,601.564c0,52.57,22.14,95.109,49.5,95.109" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_98" data-name="Path 98" d="M270.626,696.673c0-71.511,44.783-129.377,100.126-129.377" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_99" data-name="Path 99" d="M254.3,697.379s11.009-.339,14.326-2.7,16.934-5.183,17.757-1.395,16.544,18.844,4.115,18.945-28.879-1.936-32.19-3.953S254.3,697.379,254.3,697.379Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_100" data-name="Path 100" d="M290.716,710.909c-12.429.1-28.879-1.936-32.19-3.953-2.522-1.536-3.527-7.048-3.863-9.591l-.368.014s.7,8.879,4.009,10.9,19.761,4.053,32.19,3.953c3.588-.029,4.827-1.305,4.759-3.2C294.755,710.174,293.386,710.887,290.716,710.909Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_101" data-name="Path 101" d="M777.429,633.081c0,38.029,23.857,68.8,53.341,68.8" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_102" data-name="Path 102" d="M830.769,701.882c0-38.456,26.623-69.575,59.525-69.575" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_103" data-name="Path 103" d="M796.755,636.528c0,36.124,15.213,65.354,34.014,65.354" transform="translate(-56 -106.019)" fill="#6c63ff"/>
<path id="Path_104" data-name="Path 104" d="M830.769,701.882c0-49.139,30.773-88.9,68.8-88.9" transform="translate(-56 -106.019)" fill="#3f3d56"/>
<path id="Path_105" data-name="Path 105" d="M819.548,702.367s7.565-.233,9.844-1.856,11.636-3.562,12.2-.958,11.368,12.949,2.828,13.018-19.844-1.33-22.119-2.716S819.548,702.367,819.548,702.367Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_106" data-name="Path 106" d="M844.574,711.664c-8.54.069-19.844-1.33-22.119-2.716-1.733-1.056-2.423-4.843-2.654-6.59l-.253.01s.479,6.1,2.755,7.487,13.579,2.785,22.119,2.716c2.465-.02,3.317-.9,3.27-2.2C847.349,711.159,846.409,711.649,844.574,711.664Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_107" data-name="Path 107" d="M949.813,724.718s11.36-1.729,14.5-4.591,16.89-7.488,18.217-3.667,19.494,17.447,6.633,19.107-30.153,1.609-33.835-.065S949.813,724.718,949.813,724.718Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_108" data-name="Path 108" d="M989.228,734.173c-12.86,1.659-30.153,1.609-33.835-.065-2.8-1.275-4.535-6.858-5.2-9.45l-.379.061s1.833,9.109,5.516,10.783,20.975,1.725,33.835.065c3.712-.479,4.836-1.956,4.529-3.906C993.319,732.907,991.991,733.817,989.228,734.173Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_109" data-name="Path 109" d="M670.26,723.9s9.587-1.459,12.237-3.875,14.255-6.32,15.374-3.095,16.452,14.725,5.6,16.125-25.448,1.358-28.555-.055S670.26,723.9,670.26,723.9Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_110" data-name="Path 110" d="M703.524,731.875c-10.853,1.4-25.448,1.358-28.555-.055-2.367-1.076-3.827-5.788-4.39-7.976l-.32.051s1.547,7.687,4.655,9.1,17.7,1.456,28.555.055c3.133-.4,4.081-1.651,3.822-3.3C706.977,730.807,705.856,731.575,703.524,731.875Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_111" data-name="Path 111" d="M178.389,719.109s7.463-1.136,9.527-3.016,11.1-4.92,11.969-2.409,12.808,11.463,4.358,12.553-19.811,1.057-22.23-.043S178.389,719.109,178.389,719.109Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
<path id="Path_112" data-name="Path 112" d="M204.285,725.321c-8.449,1.09-19.811,1.057-22.23-.043-1.842-.838-2.979-4.506-3.417-6.209l-.249.04s1.2,5.984,3.624,7.085,13.781,1.133,22.23.043c2.439-.315,3.177-1.285,2.976-2.566C206.973,724.489,206.1,725.087,204.285,725.321Z" transform="translate(-56 -106.019)" opacity="0.2"/>
<path id="Path_113" data-name="Path 113" d="M439.7,707.337c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873,42.118-36.793,93.694-36.793S439.7,677.117,439.7,707.337Z" transform="translate(-56 -106.019)" opacity="0.1"/>
<path id="Path_114" data-name="Path 114" d="M439.7,699.9c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873S295.04,663.1,346.616,663.1,439.7,669.676,439.7,699.9Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
</g>
<g id="docusaurus_keytar" transform="translate(312.271 493.733)">
<path id="Path_40" data-name="Path 40" d="M99,52h91.791V89.153H99Z" transform="translate(5.904 -14.001)" fill="#fff" fill-rule="evenodd"/>
<path id="Path_41" data-name="Path 41" d="M24.855,163.927A21.828,21.828,0,0,1,5.947,153a21.829,21.829,0,0,0,18.908,32.782H46.71V163.927Z" transform="translate(-3 -4.634)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_42" data-name="Path 42" d="M121.861,61.1l76.514-4.782V45.39A21.854,21.854,0,0,0,176.52,23.535H78.173L75.441,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L64.513,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L53.586,18.8a3.154,3.154,0,0,0-5.464,0L45.39,23.535c-.024,0-.046,0-.071,0l-4.526-4.525a3.153,3.153,0,0,0-5.276,1.414l-1.5,5.577-5.674-1.521a3.154,3.154,0,0,0-3.863,3.864L26,34.023l-5.575,1.494a3.155,3.155,0,0,0-1.416,5.278l4.526,4.526c0,.023,0,.046,0,.07L18.8,48.122a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,59.05a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,69.977a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,80.9a3.154,3.154,0,0,0,0,5.464L23.535,89.1,18.8,91.832a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,102.76a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,113.687a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,124.615a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,135.542a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,146.469a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,157.4a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,168.324a3.154,3.154,0,0,0,0,5.464l4.732,2.732A21.854,21.854,0,0,0,45.39,198.375H176.52a21.854,21.854,0,0,0,21.855-21.855V89.1l-76.514-4.782a11.632,11.632,0,0,1,0-23.219" transform="translate(-1.681 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_43" data-name="Path 43" d="M143,186.71h32.782V143H143Z" transform="translate(9.984 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_44" data-name="Path 44" d="M196.71,159.855a5.438,5.438,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(10.912 -6.025)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_45" data-name="Path 45" d="M153,124.855h32.782V103H153Z" transform="translate(10.912 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_46" data-name="Path 46" d="M194.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.814,2.814,0,0,0,.349.035" transform="translate(12.767 -9.377)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_47" data-name="Path 47" d="M65.087,56.891a2.732,2.732,0,0,1-2.732-2.732,8.2,8.2,0,0,0-16.391,0,2.732,2.732,0,0,1-5.464,0,13.659,13.659,0,0,1,27.319,0,2.732,2.732,0,0,1-2.732,2.732" transform="translate(0.478 -15.068)" fill-rule="evenodd"/>
<path id="Path_48" data-name="Path 48" d="M103,191.347h65.565a21.854,21.854,0,0,0,21.855-21.855V93H124.855A21.854,21.854,0,0,0,103,114.855Z" transform="translate(6.275 -10.199)" fill="#ffff50" fill-rule="evenodd"/>
<path id="Path_49" data-name="Path 49" d="M173.216,129.787H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0-54.434H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.652H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186M189.585,61.611c-.013,0-.024-.007-.037-.005-3.377.115-4.974,3.492-6.384,6.472-1.471,3.114-2.608,5.139-4.473,5.078-2.064-.074-3.244-2.406-4.494-4.874-1.436-2.835-3.075-6.049-6.516-5.929-3.329.114-4.932,3.053-6.346,5.646-1.5,2.762-2.529,4.442-4.5,4.364-2.106-.076-3.225-1.972-4.52-4.167-1.444-2.443-3.112-5.191-6.487-5.1-3.272.113-4.879,2.606-6.3,4.808-1.5,2.328-2.552,3.746-4.551,3.662-2.156-.076-3.27-1.65-4.558-3.472-1.447-2.047-3.077-4.363-6.442-4.251-3.2.109-4.807,2.153-6.224,3.954-1.346,1.709-2.4,3.062-4.621,2.977a1.093,1.093,0,0,0-.079,2.186c3.3.11,4.967-1.967,6.417-3.81,1.286-1.635,2.4-3.045,4.582-3.12,2.1-.09,3.091,1.218,4.584,3.327,1.417,2,3.026,4.277,6.263,4.394,3.391.114,5.022-2.42,6.467-4.663,1.292-2,2.406-3.734,4.535-3.807,1.959-.073,3.026,1.475,4.529,4.022,1.417,2.4,3.023,5.121,6.324,5.241,3.415.118,5.064-2.863,6.5-5.5,1.245-2.282,2.419-4.437,4.5-4.509,1.959-.046,2.981,1.743,4.492,4.732,1.412,2.79,3.013,5.95,6.365,6.071l.185,0c3.348,0,4.937-3.36,6.343-6.331,1.245-2.634,2.423-5.114,4.444-5.216Z" transform="translate(7.109 -13.11)" fill-rule="evenodd"/>
<path id="Path_50" data-name="Path 50" d="M83,186.71h43.71V143H83Z" transform="translate(4.42 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 109.327, 91.085)">
<rect id="Rectangle_3" data-name="Rectangle 3" width="92.361" height="36.462" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
<g id="Group_2" data-name="Group 2" transform="translate(1.531 23.03)">
<rect id="Rectangle_4" data-name="Rectangle 4" width="5.336" height="5.336" rx="1" transform="translate(16.797 0)" fill="#4a4a4a"/>
<rect id="Rectangle_5" data-name="Rectangle 5" width="5.336" height="5.336" rx="1" transform="translate(23.12 0)" fill="#4a4a4a"/>
<rect id="Rectangle_6" data-name="Rectangle 6" width="5.336" height="5.336" rx="1" transform="translate(29.444 0)" fill="#4a4a4a"/>
<rect id="Rectangle_7" data-name="Rectangle 7" width="5.336" height="5.336" rx="1" transform="translate(35.768 0)" fill="#4a4a4a"/>
<rect id="Rectangle_8" data-name="Rectangle 8" width="5.336" height="5.336" rx="1" transform="translate(42.091 0)" fill="#4a4a4a"/>
<rect id="Rectangle_9" data-name="Rectangle 9" width="5.336" height="5.336" rx="1" transform="translate(48.415 0)" fill="#4a4a4a"/>
<rect id="Rectangle_10" data-name="Rectangle 10" width="5.336" height="5.336" rx="1" transform="translate(54.739 0)" fill="#4a4a4a"/>
<rect id="Rectangle_11" data-name="Rectangle 11" width="5.336" height="5.336" rx="1" transform="translate(61.063 0)" fill="#4a4a4a"/>
<rect id="Rectangle_12" data-name="Rectangle 12" width="5.336" height="5.336" rx="1" transform="translate(67.386 0)" fill="#4a4a4a"/>
<path id="Path_51" data-name="Path 51" d="M1.093,0H14.518a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0ZM75,0H88.426a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H75a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,75,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_3" data-name="Group 3" transform="translate(1.531 10.261)">
<path id="Path_52" data-name="Path 52" d="M1.093,0H6.218A1.093,1.093,0,0,1,7.31,1.093V4.242A1.093,1.093,0,0,1,6.218,5.335H1.093A1.093,1.093,0,0,1,0,4.242V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_13" data-name="Rectangle 13" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
<rect id="Rectangle_14" data-name="Rectangle 14" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
<rect id="Rectangle_15" data-name="Rectangle 15" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
<rect id="Rectangle_16" data-name="Rectangle 16" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
<rect id="Rectangle_17" data-name="Rectangle 17" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
<rect id="Rectangle_18" data-name="Rectangle 18" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
<rect id="Rectangle_19" data-name="Rectangle 19" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
<rect id="Rectangle_20" data-name="Rectangle 20" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
<rect id="Rectangle_21" data-name="Rectangle 21" width="5.336" height="5.336" rx="1" transform="translate(58.888 0)" fill="#4a4a4a"/>
<rect id="Rectangle_22" data-name="Rectangle 22" width="5.336" height="5.336" rx="1" transform="translate(65.212 0)" fill="#4a4a4a"/>
<rect id="Rectangle_23" data-name="Rectangle 23" width="5.336" height="5.336" rx="1" transform="translate(71.536 0)" fill="#4a4a4a"/>
<rect id="Rectangle_24" data-name="Rectangle 24" width="5.336" height="5.336" rx="1" transform="translate(77.859 0)" fill="#4a4a4a"/>
<rect id="Rectangle_25" data-name="Rectangle 25" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
</g>
<g id="Group_4" data-name="Group 4" transform="translate(91.05 9.546) rotate(180)">
<path id="Path_53" data-name="Path 53" d="M1.093,0H6.219A1.093,1.093,0,0,1,7.312,1.093v3.15A1.093,1.093,0,0,1,6.219,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_26" data-name="Rectangle 26" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
<rect id="Rectangle_27" data-name="Rectangle 27" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
<rect id="Rectangle_28" data-name="Rectangle 28" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
<rect id="Rectangle_29" data-name="Rectangle 29" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
<rect id="Rectangle_30" data-name="Rectangle 30" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
<rect id="Rectangle_31" data-name="Rectangle 31" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
<rect id="Rectangle_32" data-name="Rectangle 32" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
<rect id="Rectangle_33" data-name="Rectangle 33" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
<rect id="Rectangle_34" data-name="Rectangle 34" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
<rect id="Rectangle_35" data-name="Rectangle 35" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
<rect id="Rectangle_36" data-name="Rectangle 36" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
<rect id="Rectangle_37" data-name="Rectangle 37" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
<rect id="Rectangle_38" data-name="Rectangle 38" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
<rect id="Rectangle_39" data-name="Rectangle 39" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
<rect id="Rectangle_40" data-name="Rectangle 40" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
<rect id="Rectangle_41" data-name="Rectangle 41" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
<rect id="Rectangle_42" data-name="Rectangle 42" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
<rect id="Rectangle_43" data-name="Rectangle 43" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
<rect id="Rectangle_44" data-name="Rectangle 44" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
<rect id="Rectangle_45" data-name="Rectangle 45" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
<rect id="Rectangle_46" data-name="Rectangle 46" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
<rect id="Rectangle_47" data-name="Rectangle 47" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
<rect id="Rectangle_48" data-name="Rectangle 48" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
<rect id="Rectangle_49" data-name="Rectangle 49" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
<rect id="Rectangle_50" data-name="Rectangle 50" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
<rect id="Rectangle_51" data-name="Rectangle 51" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
</g>
<g id="Group_6" data-name="Group 6" transform="translate(1.531 16.584)">
<path id="Path_54" data-name="Path 54" d="M1.093,0h7.3A1.093,1.093,0,0,1,9.485,1.093v3.15A1.093,1.093,0,0,1,8.392,5.336h-7.3A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<g id="Group_5" data-name="Group 5" transform="translate(10.671 0)">
<rect id="Rectangle_52" data-name="Rectangle 52" width="5.336" height="5.336" rx="1" fill="#4a4a4a"/>
<rect id="Rectangle_53" data-name="Rectangle 53" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
<rect id="Rectangle_54" data-name="Rectangle 54" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
<rect id="Rectangle_55" data-name="Rectangle 55" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
<rect id="Rectangle_56" data-name="Rectangle 56" width="5.336" height="5.336" rx="1" transform="translate(25.295 0)" fill="#4a4a4a"/>
<rect id="Rectangle_57" data-name="Rectangle 57" width="5.336" height="5.336" rx="1" transform="translate(31.619 0)" fill="#4a4a4a"/>
<rect id="Rectangle_58" data-name="Rectangle 58" width="5.336" height="5.336" rx="1" transform="translate(37.942 0)" fill="#4a4a4a"/>
<rect id="Rectangle_59" data-name="Rectangle 59" width="5.336" height="5.336" rx="1" transform="translate(44.265 0)" fill="#4a4a4a"/>
<rect id="Rectangle_60" data-name="Rectangle 60" width="5.336" height="5.336" rx="1" transform="translate(50.589 0)" fill="#4a4a4a"/>
<rect id="Rectangle_61" data-name="Rectangle 61" width="5.336" height="5.336" rx="1" transform="translate(56.912 0)" fill="#4a4a4a"/>
<rect id="Rectangle_62" data-name="Rectangle 62" width="5.336" height="5.336" rx="1" transform="translate(63.236 0)" fill="#4a4a4a"/>
</g>
<path id="Path_55" data-name="Path 55" d="M1.094,0H8A1.093,1.093,0,0,1,9.091,1.093v3.15A1.093,1.093,0,0,1,8,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(80.428 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_7" data-name="Group 7" transform="translate(1.531 29.627)">
<rect id="Rectangle_63" data-name="Rectangle 63" width="5.336" height="5.336" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
<rect id="Rectangle_64" data-name="Rectangle 64" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
<rect id="Rectangle_65" data-name="Rectangle 65" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
<rect id="Rectangle_66" data-name="Rectangle 66" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
<path id="Path_56" data-name="Path 56" d="M1.093,0H31.515a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.244V1.093A1.093,1.093,0,0,1,1.093,0ZM34.687,0h3.942a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H34.687a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,34.687,0Z" transform="translate(25.294 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_67" data-name="Rectangle 67" width="5.336" height="5.336" rx="1" transform="translate(66.003 0)" fill="#4a4a4a"/>
<rect id="Rectangle_68" data-name="Rectangle 68" width="5.336" height="5.336" rx="1" transform="translate(72.327 0)" fill="#4a4a4a"/>
<rect id="Rectangle_69" data-name="Rectangle 69" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
<path id="Path_57" data-name="Path 57" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(83.59 2.273) rotate(180)" fill="#4a4a4a"/>
<path id="Path_58" data-name="Path 58" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(78.255 3.063)" fill="#4a4a4a"/>
</g>
<rect id="Rectangle_70" data-name="Rectangle 70" width="88.927" height="2.371" rx="1.085" transform="translate(1.925 1.17)" fill="#4a4a4a"/>
<rect id="Rectangle_71" data-name="Rectangle 71" width="4.986" height="1.581" rx="0.723" transform="translate(4.1 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_72" data-name="Rectangle 72" width="4.986" height="1.581" rx="0.723" transform="translate(10.923 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_73" data-name="Rectangle 73" width="4.986" height="1.581" rx="0.723" transform="translate(16.173 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_74" data-name="Rectangle 74" width="4.986" height="1.581" rx="0.723" transform="translate(21.421 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_75" data-name="Rectangle 75" width="4.986" height="1.581" rx="0.723" transform="translate(26.671 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_76" data-name="Rectangle 76" width="4.986" height="1.581" rx="0.723" transform="translate(33.232 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_77" data-name="Rectangle 77" width="4.986" height="1.581" rx="0.723" transform="translate(38.48 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_78" data-name="Rectangle 78" width="4.986" height="1.581" rx="0.723" transform="translate(43.73 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_79" data-name="Rectangle 79" width="4.986" height="1.581" rx="0.723" transform="translate(48.978 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_80" data-name="Rectangle 80" width="4.986" height="1.581" rx="0.723" transform="translate(55.54 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_81" data-name="Rectangle 81" width="4.986" height="1.581" rx="0.723" transform="translate(60.788 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_82" data-name="Rectangle 82" width="4.986" height="1.581" rx="0.723" transform="translate(66.038 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_83" data-name="Rectangle 83" width="4.986" height="1.581" rx="0.723" transform="translate(72.599 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_84" data-name="Rectangle 84" width="4.986" height="1.581" rx="0.723" transform="translate(77.847 1.566)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_85" data-name="Rectangle 85" width="4.986" height="1.581" rx="0.723" transform="translate(83.097 1.566)" fill="#d8d8d8" opacity="0.136"/>
</g>
<path id="Path_59" data-name="Path 59" d="M146.71,159.855a5.439,5.439,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(6.275 -6.025)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_60" data-name="Path 60" d="M83,124.855h43.71V103H83Z" transform="translate(4.42 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_61" data-name="Path 61" d="M134.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.811,2.811,0,0,0,.349.035" transform="translate(7.202 -9.377)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_62" data-name="Path 62" d="M143.232,42.33a2.967,2.967,0,0,1-.535-.055,2.754,2.754,0,0,1-.514-.153,2.838,2.838,0,0,1-.471-.251,4.139,4.139,0,0,1-.415-.339,3.2,3.2,0,0,1-.338-.415A2.7,2.7,0,0,1,140.5,39.6a2.968,2.968,0,0,1,.055-.535,3.152,3.152,0,0,1,.152-.514,2.874,2.874,0,0,1,.252-.47,2.633,2.633,0,0,1,.753-.754,2.837,2.837,0,0,1,.471-.251,2.753,2.753,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,4.019,4.019,0,0,1,.339.415,2.786,2.786,0,0,1,.251.47,2.864,2.864,0,0,1,.208,1.049,2.77,2.77,0,0,1-.8,1.934,4.139,4.139,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459m21.855-1.366a2.789,2.789,0,0,1-1.935-.8,4.162,4.162,0,0,1-.338-.415,2.7,2.7,0,0,1-.459-1.519,2.789,2.789,0,0,1,.8-1.934,4.139,4.139,0,0,1,.415-.339,2.838,2.838,0,0,1,.471-.251,2.752,2.752,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,2.79,2.79,0,0,1,.8,1.934,3.069,3.069,0,0,1-.055.535,2.779,2.779,0,0,1-.153.514,3.885,3.885,0,0,1-.251.47,4.02,4.02,0,0,1-.339.415,4.138,4.138,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459" transform="translate(9.753 -15.532)" fill-rule="evenodd"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 31 KiB

+170
View File
@@ -0,0 +1,170 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1041.277" height="554.141" viewBox="0 0 1041.277 554.141">
<title>Powered by React</title>
<g id="Group_24" data-name="Group 24" transform="translate(-440 -263)">
<g id="Group_23" data-name="Group 23" transform="translate(439.989 262.965)">
<path id="Path_299" data-name="Path 299" d="M1040.82,611.12q-1.74,3.75-3.47,7.4-2.7,5.67-5.33,11.12c-.78,1.61-1.56,3.19-2.32,4.77-8.6,17.57-16.63,33.11-23.45,45.89A73.21,73.21,0,0,1,942.44,719l-151.65,1.65h-1.6l-13,.14-11.12.12-34.1.37h-1.38l-17.36.19h-.53l-107,1.16-95.51,1-11.11.12-69,.75H429l-44.75.48h-.48l-141.5,1.53-42.33.46a87.991,87.991,0,0,1-10.79-.54h0c-1.22-.14-2.44-.3-3.65-.49a87.38,87.38,0,0,1-51.29-27.54C116,678.37,102.75,655,93.85,629.64q-1.93-5.49-3.6-11.12C59.44,514.37,97,380,164.6,290.08q4.25-5.64,8.64-11l.07-.08c20.79-25.52,44.1-46.84,68.93-62,44-26.91,92.75-34.49,140.7-11.9,40.57,19.12,78.45,28.11,115.17,30.55,3.71.24,7.42.42,11.11.53,84.23,2.65,163.17-27.7,255.87-47.29,3.69-.78,7.39-1.55,11.12-2.28,66.13-13.16,139.49-20.1,226.73-5.51a189.089,189.089,0,0,1,26.76,6.4q5.77,1.86,11.12,4c41.64,16.94,64.35,48.24,74,87.46q1.37,5.46,2.37,11.11C1134.3,384.41,1084.19,518.23,1040.82,611.12Z" transform="translate(-79.34 -172.91)" fill="#f2f2f2"/>
<path id="Path_300" data-name="Path 300" d="M576.36,618.52a95.21,95.21,0,0,1-1.87,11.12h93.7V618.52Zm-78.25,62.81,11.11-.09V653.77c-3.81-.17-7.52-.34-11.11-.52ZM265.19,618.52v11.12h198.5V618.52ZM1114.87,279h-74V191.51q-5.35-2.17-11.12-4V279H776.21V186.58c-3.73.73-7.43,1.5-11.12,2.28V279H509.22V236.15c-3.69-.11-7.4-.29-11.11-.53V279H242.24V217c-24.83,15.16-48.14,36.48-68.93,62h-.07v.08q-4.4,5.4-8.64,11h8.64V618.52h-83q1.66,5.63,3.6,11.12h79.39v93.62a87,87,0,0,0,12.2,2.79c1.21.19,2.43.35,3.65.49h0a87.991,87.991,0,0,0,10.79.54l42.33-.46v-97H498.11v94.21l11.11-.12V629.64H765.09V721l11.12-.12V629.64H1029.7v4.77c.76-1.58,1.54-3.16,2.32-4.77q2.63-5.45,5.33-11.12,1.73-3.64,3.47-7.4v-321h76.42Q1116.23,284.43,1114.87,279ZM242.24,618.52V290.08H498.11V618.52Zm267,0V290.08H765.09V618.52Zm520.48,0H776.21V290.08H1029.7Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_301" data-name="Path 301" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" fill="#65617d"/>
<path id="Path_302" data-name="Path 302" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" opacity="0.2"/>
<path id="Path_303" data-name="Path 303" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
<path id="Path_304" data-name="Path 304" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_305" data-name="Path 305" d="M377.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
<rect id="Rectangle_137" data-name="Rectangle 137" width="47.17" height="31.5" transform="translate(680.92 483.65)" fill="#3f3d56"/>
<rect id="Rectangle_138" data-name="Rectangle 138" width="47.17" height="31.5" transform="translate(680.92 483.65)" opacity="0.1"/>
<rect id="Rectangle_139" data-name="Rectangle 139" width="47.17" height="31.5" transform="translate(678.92 483.65)" fill="#3f3d56"/>
<path id="Path_306" data-name="Path 306" d="M298.09,483.65v4.97l-47.17,1.26v-6.23Z" opacity="0.1"/>
<path id="Path_307" data-name="Path 307" d="M460.69,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6a4,4,0,0,1,3.95,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
<path id="Path_308" data-name="Path 308" d="M265.19,481.32v181.2h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_309" data-name="Path 309" d="M194.59,319.15h177.5V467.4l-177.5,4Z" fill="#39374d"/>
<path id="Path_310" data-name="Path 310" d="M726.09,483.65v6.41l-47.17-1.26v-5.15Z" opacity="0.1"/>
<path id="Path_311" data-name="Path 311" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0L672,657.42a4,4,0,0,1-3.85-3.95V485.27a4,4,0,0,1,3.95-3.95H863.7a4,4,0,0,1,3.99,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
<path id="Path_312" data-name="Path 312" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0V481.32h0a4,4,0,0,1,4,3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_313" data-name="Path 313" d="M775.59,319.15H598.09V467.4l177.5,4Z" fill="#39374d"/>
<path id="Path_314" data-name="Path 314" d="M663.19,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h0a4,4,0,0,1-4-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6A4,4,0,0,1,663.19,485.27Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
<path id="Path_315" data-name="Path 315" d="M397.09,319.15h177.5V467.4l-177.5,4Z" fill="#4267b2"/>
<path id="Path_316" data-name="Path 316" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l202.51-1.33h.48l40.99-.28h.19l283.08-1.87h.29l.17-.01h.47l4.79-.03h1.46l74.49-.5,4.4-.02.98-.01Z" opacity="0.1"/>
<circle id="Ellipse_111" data-name="Ellipse 111" cx="51.33" cy="51.33" r="51.33" transform="translate(435.93 246.82)" fill="#fbbebe"/>
<path id="Path_317" data-name="Path 317" d="M617.94,550.07s-99.5,12-90,0c3.44-4.34,4.39-17.2,4.2-31.85-.06-4.45-.22-9.06-.45-13.65-1.1-22-3.75-43.5-3.75-43.5s87-41,77-8.5c-4,13.13-2.69,31.57.35,48.88.89,5.05,1.92,10,3,14.7a344.66,344.66,0,0,0,9.65,33.92Z" transform="translate(-79.34 -172.91)" fill="#fbbebe"/>
<path id="Path_318" data-name="Path 318" d="M585.47,546c11.51-2.13,23.7-6,34.53-1.54,2.85,1.17,5.47,2.88,8.39,3.86s6.12,1.22,9.16,1.91c10.68,2.42,19.34,10.55,24.9,20s8.44,20.14,11.26,30.72l6.9,25.83c6,22.45,12,45.09,13.39,68.3a2437.506,2437.506,0,0,1-250.84,1.43c5.44-10.34,11-21.31,10.54-33s-7.19-23.22-4.76-34.74c1.55-7.34,6.57-13.39,9.64-20.22,8.75-19.52,1.94-45.79,17.32-60.65,6.92-6.68,17-9.21,26.63-8.89,12.28.41,24.85,4.24,37,6.11C555.09,547.48,569.79,548.88,585.47,546Z" transform="translate(-79.34 -172.91)" fill="#ff6584"/>
<path id="Path_319" data-name="Path 319" d="M716.37,657.17l-.1,1.43v.1l-.17,2.3-1.33,18.51-1.61,22.3-.46,6.28-1,13.44v.17l-107,1-175.59,1.9v.84h-.14v-1.12l.45-14.36.86-28.06.74-23.79.07-2.37a10.53,10.53,0,0,1,11.42-10.17c4.72.4,10.85.89,18.18,1.41l3,.22c42.33,2.94,120.56,6.74,199.5,2,1.66-.09,3.33-.19,5-.31,12.24-.77,24.47-1.76,36.58-3a10.53,10.53,0,0,1,11.6,11.23Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_320" data-name="Path 320" d="M429.08,725.44v-.84l175.62-1.91,107-1h.3v-.17l1-13.44.43-6,1.64-22.61,1.29-17.9v-.44a10.617,10.617,0,0,0-.11-2.47.3.3,0,0,0,0-.1,10.391,10.391,0,0,0-2-4.64,10.54,10.54,0,0,0-9.42-4c-12.11,1.24-24.34,2.23-36.58,3-1.67.12-3.34.22-5,.31-78.94,4.69-157.17.89-199.5-2l-3-.22c-7.33-.52-13.46-1-18.18-1.41a10.54,10.54,0,0,0-11.24,8.53,11,11,0,0,0-.18,1.64l-.68,22.16L429.54,710l-.44,14.36v1.12Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
<path id="Path_321" data-name="Path 321" d="M716.67,664.18l-1.23,15.33-1.83,22.85-.46,5.72-1,12.81-.06.64v.17h0l-.15,1.48.11-1.48h-.29l-107,1-175.65,1.9v-.28l.49-14.36,1-28.06.64-18.65A6.36,6.36,0,0,1,434.3,658a6.25,6.25,0,0,1,3.78-.9c2.1.17,4.68.37,7.69.59,4.89.36,10.92.78,17.94,1.22,13,.82,29.31,1.7,48,2.42,52,2,122.2,2.67,188.88-3.17,3-.26,6.1-.55,9.13-.84a6.26,6.26,0,0,1,3.48.66,5.159,5.159,0,0,1,.86.54,6.14,6.14,0,0,1,2,2.46,3.564,3.564,0,0,1,.25.61A6.279,6.279,0,0,1,716.67,664.18Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_322" data-name="Path 322" d="M377.44,677.87v3.19a6.13,6.13,0,0,1-3.5,5.54l-40.1.77a6.12,6.12,0,0,1-3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_323" data-name="Path 323" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
<path id="Path_324" data-name="Path 324" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" opacity="0.1"/>
<path id="Path_325" data-name="Path 325" d="M300.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
<path id="Path_326" data-name="Path 326" d="M758.56,679.87v3.19a6.13,6.13,0,0,0,3.5,5.54l40.1.77a6.12,6.12,0,0,0,3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
<path id="Path_327" data-name="Path 327" d="M678.72,517.57l52.25,1V509.9l-52.25-1Z" opacity="0.1"/>
<path id="Path_328" data-name="Path 328" d="M676.72,517.57l52.25,1V509.9l-52.25-1Z" fill="#3f3d56"/>
<path id="Path_329" data-name="Path 329" d="M534.13,486.79c.08,7-3.16,13.6-5.91,20.07a163.491,163.491,0,0,0-12.66,74.71c.73,11,2.58,22,.73,32.9s-8.43,21.77-19,24.9c17.53,10.45,41.26,9.35,57.76-2.66,8.79-6.4,15.34-15.33,21.75-24.11a97.86,97.86,0,0,1-13.31,44.75A103.43,103.43,0,0,0,637,616.53c4.31-5.81,8.06-12.19,9.72-19.23,3.09-13-1.22-26.51-4.51-39.5a266.055,266.055,0,0,1-6.17-33c-.43-3.56-.78-7.22.1-10.7,1-4.07,3.67-7.51,5.64-11.22,5.6-10.54,5.73-23.3,2.86-34.88s-8.49-22.26-14.06-32.81c-4.46-8.46-9.3-17.31-17.46-22.28-5.1-3.1-11-4.39-16.88-5.64l-25.37-5.43c-5.55-1.19-11.26-2.38-16.87-1.51-9.47,1.48-16.14,8.32-22,15.34-4.59,5.46-15.81,15.71-16.6,22.86-.72,6.59,5.1,17.63,6.09,24.58,1.3,9,2.22,6,7.3,11.52C532,478.05,534.07,482,534.13,486.79Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
</g>
<g id="docusaurus_keytar" transform="translate(670.271 615.768)">
<path id="Path_40" data-name="Path 40" d="M99,52h43.635V69.662H99Z" transform="translate(-49.132 -33.936)" fill="#fff" fill-rule="evenodd"/>
<path id="Path_41" data-name="Path 41" d="M13.389,158.195A10.377,10.377,0,0,1,4.4,153a10.377,10.377,0,0,0,8.988,15.584H23.779V158.195Z" transform="translate(-3 -82.47)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_42" data-name="Path 42" d="M66.967,38.083l36.373-2.273V30.615A10.389,10.389,0,0,0,92.95,20.226H46.2l-1.3-2.249a1.5,1.5,0,0,0-2.6,0L41,20.226l-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-.034,0-2.152-2.151a1.5,1.5,0,0,0-2.508.672L25.21,21.4l-2.7-.723a1.5,1.5,0,0,0-1.836,1.837l.722,2.7-2.65.71a1.5,1.5,0,0,0-.673,2.509l2.152,2.152c0,.011,0,.022,0,.033l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6L20.226,41l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3A10.389,10.389,0,0,0,30.615,103.34H92.95A10.389,10.389,0,0,0,103.34,92.95V51.393L66.967,49.12a5.53,5.53,0,0,1,0-11.038" transform="translate(-9.836 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_43" data-name="Path 43" d="M143,163.779h15.584V143H143Z" transform="translate(-70.275 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_44" data-name="Path 44" d="M173.779,148.389a2.582,2.582,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-75.08 -75.262)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_45" data-name="Path 45" d="M153,113.389h15.584V103H153Z" transform="translate(-75.08 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_46" data-name="Path 46" d="M183.389,108.944a1.3,1.3,0,1,0,0-2.6,1.336,1.336,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.337,1.337,0,0,0,.166.017" transform="translate(-84.691 -57.894)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_47" data-name="Path 47" d="M52.188,48.292a1.3,1.3,0,0,1-1.3-1.3,3.9,3.9,0,0,0-7.792,0,1.3,1.3,0,1,1-2.6,0,6.493,6.493,0,0,1,12.987,0,1.3,1.3,0,0,1-1.3,1.3" transform="translate(-21.02 -28.41)" fill-rule="evenodd"/>
<path id="Path_48" data-name="Path 48" d="M103,139.752h31.168a10.389,10.389,0,0,0,10.389-10.389V93H113.389A10.389,10.389,0,0,0,103,103.389Z" transform="translate(-51.054 -53.638)" fill="#ffff50" fill-rule="evenodd"/>
<path id="Path_49" data-name="Path 49" d="M141.1,94.017H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0-25.877H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.293H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m7.782-47.993c-.006,0-.011,0-.018,0-1.605.055-2.365,1.66-3.035,3.077-.7,1.48-1.24,2.443-2.126,2.414-.981-.035-1.542-1.144-2.137-2.317-.683-1.347-1.462-2.876-3.1-2.819-1.582.054-2.344,1.451-3.017,2.684-.715,1.313-1.2,2.112-2.141,2.075-1-.036-1.533-.938-2.149-1.981-.686-1.162-1.479-2.467-3.084-2.423-1.555.053-2.319,1.239-2.994,2.286-.713,1.106-1.213,1.781-2.164,1.741-1.025-.036-1.554-.784-2.167-1.65-.688-.973-1.463-2.074-3.062-2.021a3.815,3.815,0,0,0-2.959,1.879c-.64.812-1.14,1.456-2.2,1.415a.52.52,0,0,0-.037,1.039,3.588,3.588,0,0,0,3.05-1.811c.611-.777,1.139-1.448,2.178-1.483,1-.043,1.47.579,2.179,1.582.674.953,1.438,2.033,2.977,2.089,1.612.054,2.387-1.151,3.074-2.217.614-.953,1.144-1.775,2.156-1.81.931-.035,1.438.7,2.153,1.912.674,1.141,1.437,2.434,3.006,2.491,1.623.056,2.407-1.361,3.09-2.616.592-1.085,1.15-2.109,2.14-2.143.931-.022,1.417.829,2.135,2.249.671,1.326,1.432,2.828,3.026,2.886l.088,0c1.592,0,2.347-1.6,3.015-3.01.592-1.252,1.152-2.431,2.113-2.479Z" transform="translate(-55.378 -38.552)" fill-rule="evenodd"/>
<path id="Path_50" data-name="Path 50" d="M83,163.779h20.779V143H83Z" transform="translate(-41.443 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 51.971, 43.3)">
<rect id="Rectangle_3" data-name="Rectangle 3" width="43.906" height="17.333" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
<g id="Group_2" data-name="Group 2" transform="translate(0.728 10.948)">
<rect id="Rectangle_4" data-name="Rectangle 4" width="2.537" height="2.537" rx="1" transform="translate(7.985 0)" fill="#4a4a4a"/>
<rect id="Rectangle_5" data-name="Rectangle 5" width="2.537" height="2.537" rx="1" transform="translate(10.991 0)" fill="#4a4a4a"/>
<rect id="Rectangle_6" data-name="Rectangle 6" width="2.537" height="2.537" rx="1" transform="translate(13.997 0)" fill="#4a4a4a"/>
<rect id="Rectangle_7" data-name="Rectangle 7" width="2.537" height="2.537" rx="1" transform="translate(17.003 0)" fill="#4a4a4a"/>
<rect id="Rectangle_8" data-name="Rectangle 8" width="2.537" height="2.537" rx="1" transform="translate(20.009 0)" fill="#4a4a4a"/>
<rect id="Rectangle_9" data-name="Rectangle 9" width="2.537" height="2.537" rx="1" transform="translate(23.015 0)" fill="#4a4a4a"/>
<rect id="Rectangle_10" data-name="Rectangle 10" width="2.537" height="2.537" rx="1" transform="translate(26.021 0)" fill="#4a4a4a"/>
<rect id="Rectangle_11" data-name="Rectangle 11" width="2.537" height="2.537" rx="1" transform="translate(29.028 0)" fill="#4a4a4a"/>
<rect id="Rectangle_12" data-name="Rectangle 12" width="2.537" height="2.537" rx="1" transform="translate(32.034 0)" fill="#4a4a4a"/>
<path id="Path_51" data-name="Path 51" d="M.519,0H6.9A.519.519,0,0,1,7.421.52v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0ZM35.653,0h6.383a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H35.652a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,35.652,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_3" data-name="Group 3" transform="translate(0.728 4.878)">
<path id="Path_52" data-name="Path 52" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_13" data-name="Rectangle 13" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
<rect id="Rectangle_14" data-name="Rectangle 14" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
<rect id="Rectangle_15" data-name="Rectangle 15" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
<rect id="Rectangle_16" data-name="Rectangle 16" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
<rect id="Rectangle_17" data-name="Rectangle 17" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
<rect id="Rectangle_18" data-name="Rectangle 18" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
<rect id="Rectangle_19" data-name="Rectangle 19" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
<rect id="Rectangle_20" data-name="Rectangle 20" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
<rect id="Rectangle_21" data-name="Rectangle 21" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
<rect id="Rectangle_22" data-name="Rectangle 22" width="2.537" height="2.537" rx="1" transform="translate(31 0)" fill="#4a4a4a"/>
<rect id="Rectangle_23" data-name="Rectangle 23" width="2.537" height="2.537" rx="1" transform="translate(34.006 0)" fill="#4a4a4a"/>
<rect id="Rectangle_24" data-name="Rectangle 24" width="2.537" height="2.537" rx="1" transform="translate(37.012 0)" fill="#4a4a4a"/>
<rect id="Rectangle_25" data-name="Rectangle 25" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
</g>
<g id="Group_4" data-name="Group 4" transform="translate(43.283 4.538) rotate(180)">
<path id="Path_53" data-name="Path 53" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_26" data-name="Rectangle 26" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
<rect id="Rectangle_27" data-name="Rectangle 27" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
<rect id="Rectangle_28" data-name="Rectangle 28" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
<rect id="Rectangle_29" data-name="Rectangle 29" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
<rect id="Rectangle_30" data-name="Rectangle 30" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
<rect id="Rectangle_31" data-name="Rectangle 31" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
<rect id="Rectangle_32" data-name="Rectangle 32" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
<rect id="Rectangle_33" data-name="Rectangle 33" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
<rect id="Rectangle_34" data-name="Rectangle 34" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
<rect id="Rectangle_35" data-name="Rectangle 35" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
<rect id="Rectangle_36" data-name="Rectangle 36" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
<rect id="Rectangle_37" data-name="Rectangle 37" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
<rect id="Rectangle_38" data-name="Rectangle 38" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
<rect id="Rectangle_39" data-name="Rectangle 39" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
<rect id="Rectangle_40" data-name="Rectangle 40" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
<rect id="Rectangle_41" data-name="Rectangle 41" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
<rect id="Rectangle_42" data-name="Rectangle 42" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
<rect id="Rectangle_43" data-name="Rectangle 43" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
<rect id="Rectangle_44" data-name="Rectangle 44" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
<rect id="Rectangle_45" data-name="Rectangle 45" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
<rect id="Rectangle_46" data-name="Rectangle 46" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
<rect id="Rectangle_47" data-name="Rectangle 47" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
<rect id="Rectangle_48" data-name="Rectangle 48" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
<rect id="Rectangle_49" data-name="Rectangle 49" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
<rect id="Rectangle_50" data-name="Rectangle 50" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
<rect id="Rectangle_51" data-name="Rectangle 51" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
</g>
<g id="Group_6" data-name="Group 6" transform="translate(0.728 7.883)">
<path id="Path_54" data-name="Path 54" d="M.519,0h3.47a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<g id="Group_5" data-name="Group 5" transform="translate(5.073 0)">
<rect id="Rectangle_52" data-name="Rectangle 52" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
<rect id="Rectangle_53" data-name="Rectangle 53" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
<rect id="Rectangle_54" data-name="Rectangle 54" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
<rect id="Rectangle_55" data-name="Rectangle 55" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
<rect id="Rectangle_56" data-name="Rectangle 56" width="2.537" height="2.537" rx="1" transform="translate(12.025 0)" fill="#4a4a4a"/>
<rect id="Rectangle_57" data-name="Rectangle 57" width="2.537" height="2.537" rx="1" transform="translate(15.031 0)" fill="#4a4a4a"/>
<rect id="Rectangle_58" data-name="Rectangle 58" width="2.537" height="2.537" rx="1" transform="translate(18.037 0)" fill="#4a4a4a"/>
<rect id="Rectangle_59" data-name="Rectangle 59" width="2.537" height="2.537" rx="1" transform="translate(21.042 0)" fill="#4a4a4a"/>
<rect id="Rectangle_60" data-name="Rectangle 60" width="2.537" height="2.537" rx="1" transform="translate(24.049 0)" fill="#4a4a4a"/>
<rect id="Rectangle_61" data-name="Rectangle 61" width="2.537" height="2.537" rx="1" transform="translate(27.055 0)" fill="#4a4a4a"/>
<rect id="Rectangle_62" data-name="Rectangle 62" width="2.537" height="2.537" rx="1" transform="translate(30.061 0)" fill="#4a4a4a"/>
</g>
<path id="Path_55" data-name="Path 55" d="M.52,0H3.8a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(38.234 0)" fill="#4a4a4a" fill-rule="evenodd"/>
</g>
<g id="Group_7" data-name="Group 7" transform="translate(0.728 14.084)">
<rect id="Rectangle_63" data-name="Rectangle 63" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
<rect id="Rectangle_64" data-name="Rectangle 64" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
<rect id="Rectangle_65" data-name="Rectangle 65" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
<rect id="Rectangle_66" data-name="Rectangle 66" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
<path id="Path_56" data-name="Path 56" d="M.519,0H14.981A.519.519,0,0,1,15.5.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.018V.519A.519.519,0,0,1,.519,0Zm15.97,0h1.874a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H16.489a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,16.489,0Z" transform="translate(12.024 0)" fill="#4a4a4a" fill-rule="evenodd"/>
<rect id="Rectangle_67" data-name="Rectangle 67" width="2.537" height="2.537" rx="1" transform="translate(31.376 0)" fill="#4a4a4a"/>
<rect id="Rectangle_68" data-name="Rectangle 68" width="2.537" height="2.537" rx="1" transform="translate(34.382 0)" fill="#4a4a4a"/>
<rect id="Rectangle_69" data-name="Rectangle 69" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
<path id="Path_57" data-name="Path 57" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(39.736 1.08) rotate(180)" fill="#4a4a4a"/>
<path id="Path_58" data-name="Path 58" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(37.2 1.456)" fill="#4a4a4a"/>
</g>
<rect id="Rectangle_70" data-name="Rectangle 70" width="42.273" height="1.127" rx="0.564" transform="translate(0.915 0.556)" fill="#4a4a4a"/>
<rect id="Rectangle_71" data-name="Rectangle 71" width="2.37" height="0.752" rx="0.376" transform="translate(1.949 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_72" data-name="Rectangle 72" width="2.37" height="0.752" rx="0.376" transform="translate(5.193 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_73" data-name="Rectangle 73" width="2.37" height="0.752" rx="0.376" transform="translate(7.688 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_74" data-name="Rectangle 74" width="2.37" height="0.752" rx="0.376" transform="translate(10.183 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_75" data-name="Rectangle 75" width="2.37" height="0.752" rx="0.376" transform="translate(12.679 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_76" data-name="Rectangle 76" width="2.37" height="0.752" rx="0.376" transform="translate(15.797 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_77" data-name="Rectangle 77" width="2.37" height="0.752" rx="0.376" transform="translate(18.292 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_78" data-name="Rectangle 78" width="2.37" height="0.752" rx="0.376" transform="translate(20.788 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_79" data-name="Rectangle 79" width="2.37" height="0.752" rx="0.376" transform="translate(23.283 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_80" data-name="Rectangle 80" width="2.37" height="0.752" rx="0.376" transform="translate(26.402 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_81" data-name="Rectangle 81" width="2.37" height="0.752" rx="0.376" transform="translate(28.897 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_82" data-name="Rectangle 82" width="2.37" height="0.752" rx="0.376" transform="translate(31.393 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_83" data-name="Rectangle 83" width="2.37" height="0.752" rx="0.376" transform="translate(34.512 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_84" data-name="Rectangle 84" width="2.37" height="0.752" rx="0.376" transform="translate(37.007 0.744)" fill="#d8d8d8" opacity="0.136"/>
<rect id="Rectangle_85" data-name="Rectangle 85" width="2.37" height="0.752" rx="0.376" transform="translate(39.502 0.744)" fill="#d8d8d8" opacity="0.136"/>
</g>
<path id="Path_59" data-name="Path 59" d="M123.779,148.389a2.583,2.583,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-51.054 -75.262)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_60" data-name="Path 60" d="M83,113.389h20.779V103H83Z" transform="translate(-41.443 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
<path id="Path_61" data-name="Path 61" d="M123.389,108.944a1.3,1.3,0,1,0,0-2.6,1.338,1.338,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.335,1.335,0,0,0,.166.017" transform="translate(-55.859 -57.894)" fill="#44d860" fill-rule="evenodd"/>
<path id="Path_62" data-name="Path 62" d="M141.8,38.745a1.41,1.41,0,0,1-.255-.026,1.309,1.309,0,0,1-.244-.073,1.349,1.349,0,0,1-.224-.119,1.967,1.967,0,0,1-.2-.161,1.52,1.52,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.41,1.41,0,0,1,.026-.255,1.5,1.5,0,0,1,.072-.244,1.364,1.364,0,0,1,.12-.223,1.252,1.252,0,0,1,.358-.358,1.349,1.349,0,0,1,.224-.119,1.309,1.309,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.968,1.968,0,0,1,.2.161,1.908,1.908,0,0,1,.161.2,1.322,1.322,0,0,1,.12.223,1.361,1.361,0,0,1,.1.5,1.317,1.317,0,0,1-.379.919,1.968,1.968,0,0,1-.2.161,1.346,1.346,0,0,1-.223.119,1.332,1.332,0,0,1-.5.1m10.389-.649a1.326,1.326,0,0,1-.92-.379,1.979,1.979,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.326,1.326,0,0,1,.379-.919,1.967,1.967,0,0,1,.2-.161,1.351,1.351,0,0,1,.224-.119,1.308,1.308,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.967,1.967,0,0,1,.2.161,1.326,1.326,0,0,1,.379.919,1.461,1.461,0,0,1-.026.255,1.323,1.323,0,0,1-.073.244,1.847,1.847,0,0,1-.119.223,1.911,1.911,0,0,1-.161.2,1.967,1.967,0,0,1-.2.161,1.294,1.294,0,0,1-.722.218" transform="translate(-69.074 -26.006)" fill-rule="evenodd"/>
</g>
<g id="React-icon" transform="translate(906.3 541.56)">
<path id="Path_330" data-name="Path 330" d="M263.668,117.179c0-5.827-7.3-11.35-18.487-14.775,2.582-11.4,1.434-20.477-3.622-23.382a7.861,7.861,0,0,0-4.016-1v4a4.152,4.152,0,0,1,2.044.466c2.439,1.4,3.5,6.724,2.672,13.574-.2,1.685-.52,3.461-.914,5.272a86.9,86.9,0,0,0-11.386-1.954,87.469,87.469,0,0,0-7.459-8.965c5.845-5.433,11.332-8.41,15.062-8.41V78h0c-4.931,0-11.386,3.514-17.913,9.611-6.527-6.061-12.982-9.539-17.913-9.539v4c3.712,0,9.216,2.959,15.062,8.356a84.687,84.687,0,0,0-7.405,8.947,83.732,83.732,0,0,0-11.4,1.972c-.412-1.793-.717-3.532-.932-5.2-.843-6.85.2-12.175,2.618-13.592a3.991,3.991,0,0,1,2.062-.466v-4h0a8,8,0,0,0-4.052,1c-5.039,2.9-6.168,11.96-3.568,23.328-11.153,3.443-18.415,8.947-18.415,14.757,0,5.828,7.3,11.35,18.487,14.775-2.582,11.4-1.434,20.477,3.622,23.382a7.882,7.882,0,0,0,4.034,1c4.931,0,11.386-3.514,17.913-9.611,6.527,6.061,12.982,9.539,17.913,9.539a8,8,0,0,0,4.052-1c5.039-2.9,6.168-11.96,3.568-23.328C256.406,128.511,263.668,122.988,263.668,117.179Zm-23.346-11.96c-.663,2.313-1.488,4.7-2.421,7.083-.735-1.434-1.506-2.869-2.349-4.3-.825-1.434-1.7-2.833-2.582-4.2C235.517,104.179,237.974,104.645,240.323,105.219Zm-8.212,19.1c-1.4,2.421-2.833,4.716-4.321,6.85-2.672.233-5.379.359-8.1.359-2.708,0-5.415-.126-8.069-.341q-2.232-3.2-4.339-6.814-2.044-3.523-3.73-7.136c1.112-2.4,2.367-4.805,3.712-7.154,1.4-2.421,2.833-4.716,4.321-6.85,2.672-.233,5.379-.359,8.1-.359,2.708,0,5.415.126,8.069.341q2.232,3.2,4.339,6.814,2.044,3.523,3.73,7.136C234.692,119.564,233.455,121.966,232.11,124.315Zm5.792-2.331c.968,2.4,1.793,4.805,2.474,7.136-2.349.574-4.823,1.058-7.387,1.434.879-1.381,1.757-2.8,2.582-4.25C236.4,124.871,237.167,123.419,237.9,121.984ZM219.72,141.116a73.921,73.921,0,0,1-4.985-5.738c1.614.072,3.263.126,4.931.126,1.685,0,3.353-.036,4.985-.126A69.993,69.993,0,0,1,219.72,141.116ZM206.38,130.555c-2.546-.377-5-.843-7.352-1.417.663-2.313,1.488-4.7,2.421-7.083.735,1.434,1.506,2.869,2.349,4.3S205.5,129.192,206.38,130.555ZM219.63,93.241a73.924,73.924,0,0,1,4.985,5.738c-1.614-.072-3.263-.126-4.931-.126-1.686,0-3.353.036-4.985.126A69.993,69.993,0,0,1,219.63,93.241ZM206.362,103.8c-.879,1.381-1.757,2.8-2.582,4.25-.825,1.434-1.6,2.869-2.331,4.3-.968-2.4-1.793-4.805-2.474-7.136C201.323,104.663,203.8,104.179,206.362,103.8Zm-16.227,22.449c-6.348-2.708-10.454-6.258-10.454-9.073s4.106-6.383,10.454-9.073c1.542-.663,3.228-1.255,4.967-1.811a86.122,86.122,0,0,0,4.034,10.92,84.9,84.9,0,0,0-3.981,10.866C193.38,127.525,191.694,126.915,190.134,126.252Zm9.647,25.623c-2.439-1.4-3.5-6.724-2.672-13.574.2-1.686.52-3.461.914-5.272a86.9,86.9,0,0,0,11.386,1.954,87.465,87.465,0,0,0,7.459,8.965c-5.845,5.433-11.332,8.41-15.062,8.41A4.279,4.279,0,0,1,199.781,151.875Zm42.532-13.663c.843,6.85-.2,12.175-2.618,13.592a3.99,3.99,0,0,1-2.062.466c-3.712,0-9.216-2.959-15.062-8.356a84.689,84.689,0,0,0,7.405-8.947,83.731,83.731,0,0,0,11.4-1.972A50.194,50.194,0,0,1,242.313,138.212Zm6.9-11.96c-1.542.663-3.228,1.255-4.967,1.811a86.12,86.12,0,0,0-4.034-10.92,84.9,84.9,0,0,0,3.981-10.866c1.775.556,3.461,1.165,5.039,1.829,6.348,2.708,10.454,6.258,10.454,9.073C259.67,119.994,255.564,123.562,249.216,126.252Z" fill="#61dafb"/>
<path id="Path_331" data-name="Path 331" d="M320.8,78.4Z" transform="translate(-119.082 -0.328)" fill="#61dafb"/>
<circle id="Ellipse_112" data-name="Ellipse 112" cx="8.194" cy="8.194" r="8.194" transform="translate(211.472 108.984)" fill="#61dafb"/>
<path id="Path_332" data-name="Path 332" d="M520.5,78.1Z" transform="translate(-282.975 -0.082)" fill="#61dafb"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 35 KiB

+40
View File
@@ -0,0 +1,40 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1129" height="663" viewBox="0 0 1129 663">
<title>Focus on What Matters</title>
<circle cx="321" cy="321" r="321" fill="#f2f2f2" />
<ellipse cx="559" cy="635.49998" rx="514" ry="27.50002" fill="#3f3d56" />
<ellipse cx="558" cy="627" rx="460" ry="22" opacity="0.2" />
<rect x="131" y="152.5" width="840" height="50" fill="#3f3d56" />
<path d="M166.5,727.3299A21.67009,21.67009,0,0,0,188.1701,749H984.8299A21.67009,21.67009,0,0,0,1006.5,727.3299V296h-840Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
<path d="M984.8299,236H188.1701A21.67009,21.67009,0,0,0,166.5,257.6701V296h840V257.6701A21.67009,21.67009,0,0,0,984.8299,236Z" transform="translate(-35.5 -118.5)" opacity="0.2" />
<circle cx="181" cy="147.5" r="13" fill="#3f3d56" />
<circle cx="217" cy="147.5" r="13" fill="#3f3d56" />
<circle cx="253" cy="147.5" r="13" fill="#3f3d56" />
<rect x="168" y="213.5" width="337" height="386" rx="5.33505" fill="#606060" />
<rect x="603" y="272.5" width="284" height="22" rx="5.47638" fill="#2e8555" />
<rect x="537" y="352.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="537" y="396.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="537" y="440.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="537" y="484.5" width="416" height="15" rx="5.47638" fill="#2e8555" />
<rect x="865" y="552.5" width="88" height="26" rx="7.02756" fill="#3ecc5f" />
<path d="M1088.60287,624.61594a30.11371,30.11371,0,0,0,3.98291-15.266c0-13.79652-8.54358-24.98081-19.08256-24.98081s-19.08256,11.18429-19.08256,24.98081a30.11411,30.11411,0,0,0,3.98291,15.266,31.248,31.248,0,0,0,0,30.53213,31.248,31.248,0,0,0,0,30.53208,31.248,31.248,0,0,0,0,30.53208,30.11408,30.11408,0,0,0-3.98291,15.266c0,13.79652,8.54353,24.98081,19.08256,24.98081s19.08256-11.18429,19.08256-24.98081a30.11368,30.11368,0,0,0-3.98291-15.266,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53208,31.248,31.248,0,0,0,0-30.53213Z" transform="translate(-35.5 -118.5)" fill="#3f3d56" />
<ellipse cx="1038.00321" cy="460.31783" rx="19.08256" ry="24.9808" fill="#3f3d56" />
<ellipse cx="1038.00321" cy="429.78574" rx="19.08256" ry="24.9808" fill="#3f3d56" />
<path d="M1144.93871,339.34489a91.61081,91.61081,0,0,0,7.10658-10.46092l-50.141-8.23491,54.22885.4033a91.566,91.566,0,0,0,1.74556-72.42605l-72.75449,37.74139,67.09658-49.32086a91.41255,91.41255,0,1,0-150.971,102.29805,91.45842,91.45842,0,0,0-10.42451,16.66946l65.0866,33.81447-69.40046-23.292a91.46011,91.46011,0,0,0,14.73837,85.83669,91.40575,91.40575,0,1,0,143.68892,0,91.41808,91.41808,0,0,0,0-113.02862Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M981.6885,395.8592a91.01343,91.01343,0,0,0,19.56129,56.51431,91.40575,91.40575,0,1,0,143.68892,0C1157.18982,436.82067,981.6885,385.60008,981.6885,395.8592Z" transform="translate(-35.5 -118.5)" opacity="0.1" />
<path d="M365.62,461.43628H477.094v45.12043H365.62Z" transform="translate(-35.5 -118.5)" fill="#fff" fill-rule="evenodd" />
<path d="M264.76252,608.74122a26.50931,26.50931,0,0,1-22.96231-13.27072,26.50976,26.50976,0,0,0,22.96231,39.81215H291.304V608.74122Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M384.17242,468.57061l92.92155-5.80726V449.49263a26.54091,26.54091,0,0,0-26.54143-26.54143H331.1161l-3.31768-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622-3.31767-5.74622a3.83043,3.83043,0,0,0-6.63536,0l-3.31768,5.74622L301.257,417.205a3.83043,3.83043,0,0,0-6.63536,0L291.304,422.9512c-.02919,0-.05573.004-.08625.004l-5.49674-5.49541a3.8293,3.8293,0,0,0-6.4071,1.71723l-1.81676,6.77338L270.607,424.1031a3.82993,3.82993,0,0,0-4.6912,4.69253l1.84463,6.89148-6.77072,1.81411a3.8315,3.8315,0,0,0-1.71988,6.40975l5.49673,5.49673c0,.02787-.004.05574-.004.08493l-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74621,3.31768L259.0163,466.081a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31767a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768L259.0163,558.976a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768-5.74622,3.31768a3.83042,3.83042,0,0,0,0,6.63535l5.74622,3.31768-5.74622,3.31768a3.83043,3.83043,0,0,0,0,6.63536l5.74622,3.31768A26.54091,26.54091,0,0,0,291.304,635.28265H450.55254A26.5409,26.5409,0,0,0,477.094,608.74122V502.5755l-92.92155-5.80727a14.12639,14.12639,0,0,1,0-28.19762" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M424.01111,635.28265h39.81214V582.19979H424.01111Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M490.36468,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15393-.59852A6.62668,6.62668,0,1,0,482.80568,590.21q-.2203-.22491-.44457-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39414-.10218-.59056-.15262a6.63957,6.63957,0,1,0-13.10086,0c-.1964.05042-.39414.09687-.59056.15262a6.62767,6.62767,0,1,0-11.39688,6.56369,26.52754,26.52754,0,1,0,44.23127,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M437.28182,555.65836H477.094V529.11693H437.28182Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M490.36468,545.70532a3.31768,3.31768,0,0,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M317.84538,466.081a3.31768,3.31768,0,0,1-3.31767-3.31768,9.953,9.953,0,1,0-19.90608,0,3.31768,3.31768,0,1,1-6.63535,0,16.58839,16.58839,0,1,1,33.17678,0,3.31768,3.31768,0,0,1-3.31768,3.31768" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
<path d="M370.92825,635.28265h79.62429A26.5409,26.5409,0,0,0,477.094,608.74122v-92.895H397.46968a26.54091,26.54091,0,0,0-26.54143,26.54143Z" transform="translate(-35.5 -118.5)" fill="#ffff50" fill-rule="evenodd" />
<path d="M457.21444,556.98543H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,1,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0-66.10674H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.29459H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414m0,26.54143H390.80778a1.32707,1.32707,0,0,1,0-2.65414h66.40666a1.32707,1.32707,0,0,1,0,2.65414M477.094,474.19076c-.01592,0-.0292-.008-.04512-.00663-4.10064.13934-6.04083,4.24132-7.75274,7.86024-1.78623,3.78215-3.16771,6.24122-5.43171,6.16691-2.50685-.09024-3.94007-2.92222-5.45825-5.91874-1.74377-3.44243-3.73438-7.34667-7.91333-7.20069-4.04227.138-5.98907,3.70784-7.70631,6.857-1.82738,3.35484-3.07084,5.39455-5.46887,5.30033-2.55727-.09289-3.91619-2.39536-5.48877-5.06013-1.75306-2.96733-3.77951-6.30359-7.8775-6.18946-3.97326.13669-5.92537,3.16507-7.64791,5.83912-1.82207,2.82666-3.09872,4.5492-5.52725,4.447-2.61832-.09289-3.9706-2.00388-5.53522-4.21611-1.757-2.4856-3.737-5.299-7.82308-5.16231-3.88567.13271-5.83779,2.61434-7.559,4.80135-1.635,2.07555-2.9116,3.71846-5.61218,3.615a1.32793,1.32793,0,1,0-.09555,2.65414c4.00377.134,6.03154-2.38873,7.79257-4.6275,1.562-1.9853,2.91027-3.69855,5.56441-3.78879,2.55594-.10882,3.75429,1.47968,5.56707,4.04093,1.7212,2.43385,3.67465,5.19416,7.60545,5.33616,4.11789.138,6.09921-2.93946,7.8536-5.66261,1.56861-2.43385,2.92221-4.53461,5.50734-4.62352,2.37944-.08892,3.67466,1.79154,5.50072,4.885,1.72121,2.91557,3.67069,6.21865,7.67977,6.36463,4.14709.14332,6.14965-3.47693,7.89475-6.68181,1.51155-2.77092,2.93814-5.38791,5.46621-5.4755,2.37944-.05573,3.62025,2.11668,5.45558,5.74622,1.71459,3.388,3.65875,7.22591,7.73019,7.37321l.22429.004c4.06614,0,5.99571-4.08074,7.70364-7.68905,1.51154-3.19825,2.94211-6.21069,5.3972-6.33411Z" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
<path d="M344.38682,635.28265h53.08286V582.19979H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M424.01111,602.10586a6.60242,6.60242,0,0,0-.848.08493c-.05042-.19906-.09821-.39945-.15394-.59852A6.62667,6.62667,0,1,0,416.45211,590.21q-.2203-.22491-.44458-.44589a6.62391,6.62391,0,1,0-11.39689-6.56369c-.1964-.05575-.39413-.10218-.59054-.15262a6.63957,6.63957,0,1,0-13.10084,0c-.19641.05042-.39414.09687-.59055.15262a6.62767,6.62767,0,1,0-11.39689,6.56369,26.52755,26.52755,0,1,0,44.2313,25.52756,6.6211,6.6211,0,1,0,.848-13.18579" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M344.38682,555.65836h53.08286V529.11693H344.38682Z" transform="translate(-35.5 -118.5)" fill="#3ecc5f" fill-rule="evenodd" />
<path d="M410.74039,545.70532a3.31768,3.31768,0,1,0,0-6.63536,3.41133,3.41133,0,0,0-.42333.04247c-.02655-.09953-.04911-.19907-.077-.29859a3.319,3.319,0,0,0-1.278-6.37923,3.28174,3.28174,0,0,0-2.00122.68742q-.10947-.11346-.22294-.22295a3.282,3.282,0,0,0,.67149-1.98265,3.31768,3.31768,0,0,0-6.37-1.2992,13.27078,13.27078,0,1,0,0,25.54082,3.31768,3.31768,0,0,0,6.37-1.2992,3.282,3.282,0,0,0-.67149-1.98265q.11347-.10947.22294-.22294a3.28174,3.28174,0,0,0,2.00122.68742,3.31768,3.31768,0,0,0,1.278-6.37923c.02786-.0982.05042-.19907.077-.29859a3.41325,3.41325,0,0,0,.42333.04246" transform="translate(-35.5 -118.5)" fill="#44d860" fill-rule="evenodd" />
<path d="M424.01111,447.8338a3.60349,3.60349,0,0,1-.65028-.06636,3.34415,3.34415,0,0,1-.62372-.18579,3.44679,3.44679,0,0,1-.572-.30522,5.02708,5.02708,0,0,1-.50429-.4114,3.88726,3.88726,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.60248,3.60248,0,0,1,.06636-.65027,3.82638,3.82638,0,0,1,.18447-.62373,3.48858,3.48858,0,0,1,.30656-.57064,3.197,3.197,0,0,1,.91436-.91568,3.44685,3.44685,0,0,1,.572-.30523,3.344,3.344,0,0,1,.62372-.18578,3.06907,3.06907,0,0,1,1.30053,0,3.22332,3.22332,0,0,1,1.19436.491,5.02835,5.02835,0,0,1,.50429.41139,4.8801,4.8801,0,0,1,.41139.50429,3.38246,3.38246,0,0,1,.30522.57064,3.47806,3.47806,0,0,1,.25215,1.274A3.36394,3.36394,0,0,1,426.36,446.865a5.02708,5.02708,0,0,1-.50429.4114,3.3057,3.3057,0,0,1-1.84463.55737m26.54143-1.65884a3.38754,3.38754,0,0,1-2.35024-.96877,5.04185,5.04185,0,0,1-.41007-.50428,3.27532,3.27532,0,0,1-.55737-1.84463,3.38659,3.38659,0,0,1,.96744-2.34892,5.02559,5.02559,0,0,1,.50429-.41139,3.44685,3.44685,0,0,1,.572-.30523,3.3432,3.3432,0,0,1,.62373-.18579,3.06952,3.06952,0,0,1,1.30052,0,3.22356,3.22356,0,0,1,1.19436.491,5.02559,5.02559,0,0,1,.50429.41139,3.38792,3.38792,0,0,1,.96876,2.34892,3.72635,3.72635,0,0,1-.06636.65026,3.37387,3.37387,0,0,1-.18579.62373,4.71469,4.71469,0,0,1-.30522.57064,4.8801,4.8801,0,0,1-.41139.50429,5.02559,5.02559,0,0,1-.50429.41139,3.30547,3.30547,0,0,1-1.84463.55737" transform="translate(-35.5 -118.5)" fill-rule="evenodd" />
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

+1
View File
@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
+8
View File
@@ -0,0 +1,8 @@
{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": "."
},
"exclude": [".docusaurus", "build"]
}
+14 -14
View File
@@ -3,25 +3,25 @@ module github.com/starfleetcptn/gomft
go 1.24.0
require (
github.com/a-h/templ v0.3.833
github.com/gin-contrib/sessions v1.0.2
github.com/a-h/templ v0.3.857
github.com/gin-contrib/sessions v1.0.3
github.com/gin-gonic/gin v1.10.0
github.com/glebarez/sqlite v1.11.0
github.com/go-gormigrate/gormigrate/v2 v2.1.3
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/go-gormigrate/gormigrate/v2 v2.1.4
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/joho/godotenv v1.5.1
github.com/pquerna/otp v1.4.0
github.com/robfig/cron/v3 v3.0.1
github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.36.0
golang.org/x/crypto v0.37.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/gorm v1.25.12
)
require (
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/bytedance/sonic v1.12.9 // indirect
github.com/bytedance/sonic/loader v0.2.3 // indirect
github.com/bytedance/sonic v1.13.2 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
@@ -30,12 +30,12 @@ require (
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.25.0 // indirect
github.com/go-playground/validator/v10 v10.26.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/context v1.1.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/sessions v1.2.2 // indirect
github.com/gorilla/sessions v1.4.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
@@ -50,11 +50,11 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.14.0 // indirect
golang.org/x/net v0.37.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
golang.org/x/arch v0.16.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
+28
View File
@@ -1,12 +1,18 @@
github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
github.com/a-h/templ v0.3.857 h1:6EqcJuGZW4OL+2iZ3MD+NnIcG7nGkaQeF2Zq5kf9ZGg=
github.com/a-h/templ v0.3.857/go.mod h1:qhrhAkRFubE7khxLZHsBFHfX+gWwVNKbzKeF9GlPV4M=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bytedance/sonic v1.12.9 h1:Od1BvK55NnewtGaJsTDeAOSnLVO2BTSLOe0+ooKokmQ=
github.com/bytedance/sonic v1.12.9/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8=
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0=
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
@@ -19,6 +25,8 @@ github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3G
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/gin-contrib/sessions v1.0.2 h1:UaIjUvTH1cMeOdj3in6dl+Xb6It8RiKRF9Z1anbUyCA=
github.com/gin-contrib/sessions v1.0.2/go.mod h1:KxKxWqWP5LJVDCInulOl4WbLzK2KSPlLesfZ66wRvMs=
github.com/gin-contrib/sessions v1.0.3 h1:AZ4j0AalLsGqdrKNbbrKcXx9OJZqViirvNGsJTxcQps=
github.com/gin-contrib/sessions v1.0.3/go.mod h1:5i4XMx4KPtQihnzxEqG9u1K446lO3G19jAi2GtbfsAI=
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
@@ -29,6 +37,8 @@ github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GM
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-gormigrate/gormigrate/v2 v2.1.3 h1:ei3Vq/rpPI/jCJY9mRHJAKg5vU+EhZyWhBAkaAomQuw=
github.com/go-gormigrate/gormigrate/v2 v2.1.3/go.mod h1:VJ9FIOBAur+NmQ8c4tDVwOuiJcgupTG105FexPFrXzA=
github.com/go-gormigrate/gormigrate/v2 v2.1.4 h1:KOPEt27qy1cNzHfMZbp9YTmEuzkY4F4wrdsJW9WFk1U=
github.com/go-gormigrate/gormigrate/v2 v2.1.4/go.mod h1:y/6gPAH6QGAgP1UfHMiXcqGeJ88/GRQbfCReE1JJD5Y=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -37,10 +47,14 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -56,6 +70,8 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@@ -108,17 +124,29 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=