Contributing to Smyles Station
Thank you for your interest in contributing to Smyles Station! This guide will help you get started with development and understand the project's structure and conventions.
Table of Contents
- Getting Started
- Development Workflow
- Project Architecture
- Code Organization
- Adding New Features
- Testing
- Code Style
- Security Guidelines
- Pull Request Process
Getting Started
Prerequisites
- Node.js >= 23.0.0
- npm (comes with Node.js)
- Git
- A code editor (VS Code recommended)
Initial Setup
-
Fork and clone the repository:
git clone https://github.com/buff-sudo/smyles-station.git cd smyles-station -
Install dependencies:
npm install -
Start the development server:
npm start
The application will start in development mode with hot-reload enabled.
Development Workflow
Running the Application
# Start in development mode (hot-reload enabled)
npm start
# Build all packages
npm run build
# Run type checking
npm run typecheck
# Run end-to-end tests
npm test
# Compile executable for distribution
npm run compile
Development Mode Features
- Hot-reload for renderer changes (React components, CSS)
- Automatic restart on main process changes
- React DevTools available in development
- Source maps enabled for debugging
Project Architecture
Smyles Station follows Electron's security-first architecture with strict process isolation.
Monorepo Structure
The project is organized as a monorepo with the following packages:
packages/
main/ # Electron main process (Node.js)
src/
index.ts # Application entry point
modules/ # Feature modules
preload/ # Preload scripts (secure bridge)
src/
index.ts # Exposed APIs
renderer/ # React UI (browser context)
src/
App.tsx # Main React component
components/
integrate-renderer/ # Build tooling
electron-versions/ # Helper utilities
Process Communication
graph TB
R["Renderer<br/>(packages/renderer)<br/><br/>React UI - Browser context<br/>no Node.js"]
P["Preload<br/>(packages/preload)<br/><br/>Secure bridge<br/>Limited Electron APIs"]
M["Main<br/>(packages/main)<br/><br/>Node.js runtime<br/>Full system access"]
R -->|Import/Call| P
P -->|IPC| M
Code Organization
Main Process Modules
All main process features are implemented as modules in packages/main/src/modules/:
- AdminModule.ts - Password-protected admin panel
- SessionModule.ts - Time-limited session management
- UsageStatsModule.ts - Usage tracking and statistics
- ShutdownScheduleModule.ts - Automatic shutdowns
- WindowManager.ts - Window creation and management
- BlockNotAllowedOrigins.ts - URL whitelist enforcement
- ExternalUrls.ts - External URL handling
- AbstractSecurityModule.ts - Base class for security features
Module Pattern
Each module follows a consistent pattern:
export class MyModule {
constructor(private readonly browserWindow: BrowserWindow) {
this.init();
}
private init() {
// Setup IPC handlers, event listeners, etc.
}
// Public methods exposed via IPC
// Private helper methods
}
Adding New Features
1. Main Process Features
To add a new feature to the main process:
-
Create a new module in
packages/main/src/modules/:// packages/main/src/modules/MyFeatureModule.ts import {BrowserWindow, ipcMain} from 'electron'; export class MyFeatureModule { constructor(private readonly browserWindow: BrowserWindow) { this.setupIpcHandlers(); } private setupIpcHandlers() { ipcMain.handle('my-feature:action', async () => { // Implementation return result; }); } } -
Register the module in
packages/main/src/index.ts:import {MyFeatureModule} from './modules/MyFeatureModule'; // In the app initialization new MyFeatureModule(browserWindow);
2. Exposing APIs to Renderer
To make functionality available to the React UI:
-
Add the function to
packages/preload/src/index.ts:export async function myFeatureAction(): Promise<Result> { return ipcRenderer.invoke('my-feature:action'); } -
Update TypeScript types in
packages/renderer/src/electron.d.ts:interface Window { myFeatureAction: () => Promise<Result>; } -
Use in React components:
import {myFeatureAction} from '@app/preload'; const result = await myFeatureAction();
3. UI Components
Create new React components in packages/renderer/src/components/:
// packages/renderer/src/components/MyComponent.tsx
import React from 'react';
import './MyComponent.css';
export const MyComponent: React.FC = () => {
return (
<div className="my-component">
{/* Component content */}
</div>
);
};
Testing
End-to-End Tests
E2E tests are located in the tests/ directory and use Playwright:
// tests/my-feature.spec.ts
import {test, expect} from '@playwright/test';
import {ElectronApplication} from 'playwright';
test('my feature works', async ({page}) => {
// Test implementation
});
Run tests with:
npm test
Manual Testing Checklist
Before submitting a PR, manually verify:
- [ ] Application starts without errors
- [ ] Feature works in both development and compiled modes
- [ ] No console errors in DevTools
- [ ] TypeScript compilation passes (
npm run typecheck) - [ ] UI is responsive and accessible
- [ ] Security features (URL blocking, session limits) still work
Code Style
TypeScript
- Use TypeScript for all new code
- Enable strict mode
- Prefer interfaces over types for object shapes
- Use async/await over promises
- Avoid
any- use proper types orunknown
Naming Conventions
- Files: PascalCase for modules (e.g.,
SessionModule.ts) - Components: PascalCase (e.g.,
AdminDashboard.tsx) - Functions: camelCase (e.g.,
startSession) - Constants: UPPER_SNAKE_CASE (e.g.,
MAX_SESSION_TIME) - CSS classes: kebab-case (e.g.,
session-timer)
File Organization
// 1. Imports (external first, then internal)
import {BrowserWindow} from 'electron';
import {myHelper} from './helpers';
// 2. Types/Interfaces
interface MyConfig {
// ...
}
// 3. Constants
const DEFAULT_TIMEOUT = 5000;
// 4. Class/Function definitions
export class MyModule {
// ...
}
Security Guidelines
Smyles Station is designed for use with children, so security is critical.
Security Principles
- Never expose Node.js APIs to renderer - Always use the preload bridge
- Validate all inputs - Especially from IPC and user input
- Sanitize URLs - Prevent navigation to unauthorized sites
- Use context isolation - Already enabled, don't disable it
- Enable sandbox - Keep renderer processes sandboxed
- Minimize privileges - Only request permissions you need
Security Checklist
Before adding new features:
- [ ] Does this expose any system APIs to the renderer?
- [ ] Are all IPC handlers validated and sanitized?
- [ ] Could this be used to bypass URL restrictions?
- [ ] Does this handle user input safely?
- [ ] Could this be exploited by malicious web content?
Common Security Pitfalls
DON'T:
// Exposing shell access to renderer
ipcMain.handle('run-command', (_, cmd) => {
exec(cmd); // Dangerous!
});
DO:
// Specific, validated operations
ipcMain.handle('shutdown-system', async () => {
// Verify admin authentication first
if (!isAdminAuthenticated()) return;
// Execute specific, safe operation
await shutdownSystem();
});
Pull Request Process
Before Submitting
-
Create a feature branch:
git checkout -b feature/my-new-feature -
Make your changes:
- Write clean, documented code
- Follow the code style guidelines
-
Add tests if applicable
-
Test thoroughly:
npm run typecheck npm run build npm test -
Commit with clear messages:
git commit -m "Add scheduled shutdown feature"
Submitting the PR
-
Push to your fork:
git push origin feature/my-new-feature -
Open a Pull Request with:
- Clear title describing the change
- Description of what changed and why
- Screenshots/videos for UI changes
-
Reference any related issues
-
Respond to review feedback
PR Review Criteria
Your PR will be reviewed for:
- Code quality and style
- Security implications
- Test coverage
- Documentation updates
- Breaking changes (if any)
Questions or Issues?
- Bug reports: Open an issue with steps to reproduce
- Feature requests: Open an issue describing the use case
- Questions: Open a discussion or contact smyles-station-safety@proton.me
- Security issues: Email smyles-station-safety@proton.me (do not open public issues)
License
By contributing, you agree that your contributions will be licensed under the same license as the project.
Thank you for contributing to Smyles Station!