TimeBit Application

TimeBit

FH Campus Wien - 2025

TimeBit is a modern time tracking and project management application developed as a university project at FH Campus Wien. Built with Node.js, Express, MySQL, and vanilla JavaScript, it features JWT authentication, Google OAuth integration, and real-time project management capabilities. The application helps teams and individuals manage their time effectively and track projects or hobbies efficiently. A link to the GitHub repository can be found here.

Role

Lead Developer

Responsibilities

Backend Development

Frontend Development

Database Design

API Implementation

Authentication System

Team

Orsonlya Nemere

Sara Hikal

1. Approach


TimeBit was developed as a comprehensive full-stack web application focusing on modern web development practices. The project aimed to create a practical, user-friendly time tracking solution while implementing industry-standard technologies and best practices. The development approach emphasized modular architecture, secure authentication, and responsive design to ensure scalability and maintainability.

Background: I’ve always enjoyed working on projects, and I know I’m not alone in that. The problem is, a lot of projects never get finished, and even when they do, it’s hard to see how much time actually went into them. That’s exactly what we set out to solve with this project. TimeBit is a time-tracking app designed to help people keep track of how much time they spend on their projects or hobbies. Over time, it not only helps users stay focused on their goals, but also shows them how their time investment changes, reveals patterns in their work habits, and keeps their progress visible and motivating.

1.1 Planning


The project planning phase involved several key decisions that shaped the final application:

Technology Stack Selection: Chose Node.js with Express for the backend due to its JavaScript ecosystem and rapid development capabilities. MySQL was selected for data persistence with Sequelize ORM for database management.

Frontend Architecture: Decided to use vanilla JavaScript instead of a framework to demonstrate core web development skills and maintain full control over the application's behavior and performance.

Authentication Strategy: Implemented JWT-based authentication with refresh tokens for security, complemented by Google OAuth for enhanced user experience and social login capabilities.

The project structure was designed with clear separation of concerns, following the MVC (Model-View-Controller) pattern on the backend and component-based architecture on the frontend. This modular approach facilitated development, testing, and future maintenance.

Project Structure

Source 1: Project structure showing the organized backend and frontend architecture.

1.2 Architecture


The application follows a modern client-server architecture with clear separation between frontend and backend components:

Backend (Node.js/Express): RESTful API server handling authentication, data persistence, and business logic. Organized into controllers, routes, models, and middleware for maintainability.

Frontend (Vanilla JavaScript): Single Page Application (SPA) with dynamic content loading, modular components, and responsive design using custom CSS and Inter font family.

Database (MySQL): Relational database with Sequelize ORM for data modeling, relationships, and query optimization.

The architecture emphasizes scalability, security, and user experience, with features like automatic token refresh, error handling, and loading states for smooth user interactions.

2. Development


The development process was structured around building a robust, scalable application with modern web development practices. Each component was developed with careful attention to security, performance, and user experience.

2.1 Backend


The backend is built with Node.js and Express, providing a RESTful API with comprehensive functionality. The server handles authentication, project management, user data, and external service integrations.

                                        // Main server configuration
import express from "express";
import setupSwagger from './utils/swagger.js';

// Import API routes
import authRoutes from "./routes/authRoutes.js"
import projectRoutes from "./routes/projectRoutes.js";
import notificationRoutes from "./routes/notificationRoutes.js";

// Initialize the Express app
const app = express();
const port = 3000;

// Mount API routes
app.use(express.json());
app.use('/auth', authRoutes);
app.use('/projects', projectRoutes);
app.use("/api", notificationRoutes);

// Setup Swagger documentation
setupSwagger(app);

// Serve frontend static files
app.use(express.static(path.join(__dirname, "../frontend")));

app.listen(port, () => {
  console.log(`✅ Server is running at: http://localhost:${port}`);
});
                                      

Code Snippet 1: Main server configuration

The backend implements a modular structure with separate routes for different functionalities. Authentication routes handle user registration, login, and Google OAuth integration. Project routes manage CRUD operations for user projects, while notification routes handle email services via SendGrid.

Security is implemented through JWT tokens with automatic refresh capabilities, input validation, and proper error handling. The API is fully documented using Swagger/OpenAPI for easy testing and integration.

2.2 Frontend


The frontend is built as a Single Page Application using vanilla JavaScript, providing a smooth user experience with dynamic content loading and responsive design.

                                        // Main application entry point
window.addEventListener("DOMContentLoaded", () => {
    if (!checkAuth()){
      return;
    }
    loadMainScreen();
});

// Function to load the main screen after successful login
export async function loadMainScreen() {
  const token = localStorage.getItem('token');
  if (token) {
      try {
          // Load the sidebar and header with user information
          await loadSidebar();
          await loadHeader();
          loadPage("calendar", true);
      } catch (error) {
          console.error('Error loading main screen:', error);
          localStorage.clear(); // Clear invalid tokens
          loadPage("login", false);
      }
  } else {
      // No token found, redirect to login
      loadPage("login", false);
  }
}
                                      

Code Snippet 2: Frontend application initialization

The frontend uses a component-based architecture with dynamic loading of HTML, CSS, and JavaScript files. The application includes a reusable loading screen component, modular sidebar and header components, and a content loader utility for seamless page transitions.

Authentication is handled through JWT tokens stored in localStorage, with automatic token refresh and error handling. The UI is built with custom CSS using the Inter font family and follows modern design principles for optimal user experience.

Source 2: Frontend demo showing the responsive design and mobile-friendly interface.

2.3 Database


The database design follows relational database principles with proper relationships between entities. The application uses MySQL with Sequelize ORM for data modeling and management.

                                        // User model definition
const User = sequelize.define('User', {
  email: {
    type: DataTypes.STRING,
    unique: true,
    allowNull: false
  },
  password: {
    type: DataTypes.STRING,
    allowNull: false
  },
  first_name: {
    type: DataTypes.STRING,
    allowNull: false
  },
  last_name: {
    type: DataTypes.STRING,
    allowNull: false
  }
}, {
    tableName: 'users',
    timestamps: true,
    underscored: true
});

// Project model with relationships
const Project = sequelize.define('Project', {
    title: {
        type: DataTypes.STRING,
        allowNull: false
    },
    category: {
        type: DataTypes.STRING,
        allowNull: false
    },
    weekly_hours: {
        type: DataTypes.INTEGER,
        allowNull: false
    },
    status: {
        type: DataTypes.ENUM('ongoing', 'finished'),
        defaultValue: 'ongoing'
    }
}, {
    tableName: 'projects',
    timestamps: false,
    underscored: true
});

// Define relationships
Project.belongsTo(User, { foreignKey: 'user_id' });
User.hasMany(Project, { foreignKey: 'user_id' });
                                      

Code Snippet 3: Database models and relationships

The database schema includes three main entities: Users, Projects, and TimeEntries. Users can have multiple projects, and projects can have multiple time entries. The design ensures data integrity through foreign key relationships and proper constraints.

Sequelize ORM provides an abstraction layer that simplifies database operations while maintaining type safety and relationship management. The models include proper validation, timestamps, and indexing for optimal performance.

2.4 Authentication


The authentication system implements multiple layers of security and user convenience, including JWT tokens, refresh tokens, and Google OAuth integration.

                                        // JWT Authentication middleware
export const authMiddleware = (req, res, next) => {
    try {
        const token = req.header('Authorization')?.replace('Bearer ', '');
        
        if (!token) {
            return res.status(401).json({ 
                success: false,
                message: 'No token, authorization denied' 
            });
        }

        const decoded = jwt.verify(token, config.jwtSecret);
        req.user = { id: decoded.userId };
        next();
    } catch (error) {
        if (error.name === 'TokenExpiredError') {
            return res.status(401).json({ 
                success: false,
                message: 'Token has expired' 
            });
        }
        
        return res.status(401).json({ 
            success: false,
            message: 'Token is not valid' 
        });
    }
};

// Google OAuth integration
export const googleAuth = async (req, res) => {
    const { token } = req.body;
    const client = new OAuth2Client(config.googleClientId);

    try {
        const ticket = await client.verifyIdToken({
            idToken: token,
            audience: config.googleClientId
        });

        const payload = ticket.getPayload();
        const { email, given_name: first_name, family_name: last_name } = payload;
        
        // Check if user exists or create new user
        let user = await User.findOne({ where: { email } });
        if (!user) {
            user = await User.create({
                email,
                first_name,
                last_name,
                password: await bcrypt.hash(Math.random().toString(36), 10)
            });
        }

        // Generate JWT tokens
        const accessToken = jwt.sign(
            { userId: user.id },
            config.jwtSecret,
            { expiresIn: '24h' }
        );

        return res.json({
            success: true,
            token: accessToken,
            user: {
                id: user.id,
                email: user.email,
                firstName: user.first_name,
                lastName: user.last_name
            }
        });
    } catch (error) {
        return res.status(401).json({
            success: false,
            message: 'Google authentication failed'
        });
    }
};
                                      

Code Snippet 4: Authentication system implementation

The authentication system provides both traditional email/password login and Google OAuth integration. JWT tokens are used for session management with automatic refresh capabilities. The system includes proper error handling, token validation, and secure password hashing using bcrypt.

Security measures include token expiration, secure token storage, and proper validation of user credentials. The Google OAuth integration allows users to sign in with their Google accounts, enhancing user experience while maintaining security standards.

3. Features


TimeBit includes a comprehensive set of features designed to provide a complete time tracking and project management solution:

User Authentication: Secure registration and login with JWT tokens, Google OAuth integration, and automatic token refresh for seamless user experience.

Project Management: Create, view, update, and delete projects with categories (study, health, work, hobby), weekly hour allocations, and status tracking (ongoing/finished).

Email Notifications: Automated email notifications via SendGrid when projects are created, keeping users informed of their project activities.

Responsive Design: Mobile-friendly interface with custom CSS styling using the Inter font family and modern design principles.

API Documentation: Comprehensive Swagger/OpenAPI documentation for all endpoints, facilitating testing and integration.

External Integrations: Weather API integration and notification services for enhanced functionality.

Source 2: Application demo showing time entry creation and management features.

4. Lessons Learned


Working on TimeBit was a big step forward for me in full-stack web development. I didn’t just build a working app, I got hands-on experience with the kind of challenges that come up when you’re trying to make something scalable, secure, and actually nice to use.

One thing I really came to appreciate was the value of modular architecture. Breaking the backend into controllers, routes, models, and middleware wasn’t just “best practice”, it kept the project organized and made my life a lot easier when adding new features or fixing bugs.

A personal goal for me was to really understand how authentication and security work in a real app. I got to implement JWT tokens, secure password hashing, and OAuth integrations. Setting up an automatic token refresh was a nice win, it kept things smooth for the user without compromising security.

I decided to stick with vanilla JavaScript instead of using a framework. It was definitely more work, but it forced me to understand the fundamentals and solve problems from scratch. While frameworks make life easier, doing it this way gave me complete control over how the app behaved and performed.

Another big takeaway was how important good API design and documentation really is. Writing a clean RESTful API and documenting it with Swagger made testing and integration so much smoother. It was one of those “spend time now, save time later” lessons.

In the end, TimeBit was more than just a finished app, it was a crash course in building something from the ground up, intensely working with the backend and frontend, and making different technologies work together to solve a real problem: tracking your time efficiently in a user-friendly, secure, lightweight app. This App honestly took a lot of sweat and hard work to finish as a group, so I sincerely thank to all my team members who contributed to it.