diff --git a/main.go b/main.go
index 9725854..b0fb491 100644
--- a/main.go
+++ b/main.go
@@ -5,18 +5,21 @@ import (
 	"database/sql"
 	"embed"
 	"encoding/json"
+	"flag"
 	"fmt"
-	"github.com/num30/config"
 	"github.com/pressly/goose/v3"
 	"go.uber.org/zap"
 	"io"
 	"net/http"
+	"os"
+	"strconv"
 	"strings"
 
 	"github.com/labstack/echo/v4"
 	"github.com/labstack/echo/v4/middleware"
 	_ "github.com/mattn/go-sqlite3"
 	"golang.org/x/oauth2"
+	"gopkg.in/yaml.v2"
 )
 
 //go:embed static/*
@@ -30,7 +33,7 @@ type OAuthConfig struct {
 	ClientSecret string `config:"client_secret" yaml:"client_secret"`
 	AuthURL      string `config:"auth_url" yaml:"auth_url"`
 	TokenURL     string `config:"token_url" yaml:"token_url"`
-	UserInfoURL  string `config:"userinfo_url" yaml:"userinfo_url"`
+	UserInfoURL  string `config:"user_info_url" yaml:"user_info_url"`
 }
 
 type DBConfig struct {
@@ -61,34 +64,95 @@ var (
 var db *sql.DB
 
 func main() {
-	// Use the global cfg variable instead of declaring a new one
-	cfgReader := config.NewConfReader("config").WithSearchDirs("./", ".", "../", "../../")
-	cfgErr := cfgReader.Read(&cfg)
+	// Load configuration from YAML file, environment variables, and flags
+	configFile := flag.String("config", "config.yaml", "Path to config file")
+	serverPort := flag.Int("port", 0, "Server port (overrides config file)")
+	oauthClientID := flag.String("oauth-client-id", "", "OAuth Client ID (overrides config file)")
+	oauthClientSecret := flag.String("oauth-client-secret", "", "OAuth Client Secret (overrides config file)")
+	oauthAuthURL := flag.String("oauth-auth-url", "", "OAuth Auth URL (overrides config file)")
+	oauthTokenURL := flag.String("oauth-token-url", "", "OAuth Token URL (overrides config file)")
+	oauthUserInfoURL := flag.String("oauth-user-info-url", "", "OAuth User Info URL (overrides config file)")
+	flag.Parse()
+
+	// Set default values
+	cfg = Config{
+		Env: "dev",
+		Server: struct {
+			Port int `config:"port"`
+		}{Port: 8088},
+		OAuth: OAuthConfig{},
+		DB: DBConfig{
+			Driver: "sqlite3",
+			DBName: "./inventor.sqlite",
+		},
+	}
+
+	yamlData, err := os.ReadFile(*configFile)
+	if err != nil {
+		fmt.Printf("Warning: Could not read config file: %v\n", err)
+	} else {
+		if err := yaml.Unmarshal(yamlData, &cfg); err != nil {
+			fmt.Printf("Warning: Could not parse config file: %v\n", err)
+		} else {
+			fmt.Println("Successfully loaded configuration from", *configFile)
+		}
+	}
+
+	if envPort := os.Getenv("INVENTOR_SERVER_PORT"); envPort != "" {
+		if port, err := strconv.Atoi(envPort); err == nil {
+			cfg.Server.Port = port
+		}
+	}
+	if envClientID := os.Getenv("INVENTOR_OAUTH_CLIENT_ID"); envClientID != "" {
+		cfg.OAuth.ClientID = envClientID
+	}
+	if envClientSecret := os.Getenv("INVENTOR_OAUTH_CLIENT_SECRET"); envClientSecret != "" {
+		cfg.OAuth.ClientSecret = envClientSecret
+	}
+	if envAuthURL := os.Getenv("INVENTOR_OAUTH_AUTH_URL"); envAuthURL != "" {
+		cfg.OAuth.AuthURL = envAuthURL
+	}
+	if envTokenURL := os.Getenv("INVENTOR_OAUTH_TOKEN_URL"); envTokenURL != "" {
+		cfg.OAuth.TokenURL = envTokenURL
+	}
+	if envUserInfoURL := os.Getenv("INVENTOR_OAUTH_USER_INFO_URL"); envUserInfoURL != "" {
+		cfg.OAuth.UserInfoURL = envUserInfoURL
+	}
+
+	// 3. Override with command line flags (highest priority)
+	if *serverPort != 0 {
+		cfg.Server.Port = *serverPort
+	}
+	if *oauthClientID != "" {
+		cfg.OAuth.ClientID = *oauthClientID
+	}
+	if *oauthClientSecret != "" {
+		cfg.OAuth.ClientSecret = *oauthClientSecret
+	}
+	if *oauthAuthURL != "" {
+		cfg.OAuth.AuthURL = *oauthAuthURL
+	}
+	if *oauthTokenURL != "" {
+		cfg.OAuth.TokenURL = *oauthTokenURL
+	}
+	if *oauthUserInfoURL != "" {
+		cfg.OAuth.UserInfoURL = *oauthUserInfoURL
+	}
 
 	zapcfg := zap.NewProductionConfig()
 	if cfg.Env == "dev" {
 		zapcfg = zap.NewDevelopmentConfig()
 	}
-	logger, err := zapcfg.Build()
+	logger, err = zapcfg.Build()
 	if err != nil {
 		panic(fmt.Sprintf("Failed to initialize logger: %v", err))
 	}
 	defer logger.Sync()
 
-	if cfgErr != nil {
-		logger.Fatal("Failed to load config", zap.Error(cfgErr))
-	}
+	// Configuration errors are now handled inline during loading
 
 	// Print the raw config to see what's actually loaded
-	logger.Info("Raw config loaded", zap.Any("config", cfg))
-
-	// Add detailed logging of the OAuth config
-	logger.Info("OAuth Configuration",
-		zap.String("ClientID", cfg.OAuth.ClientID),
-		zap.String("ClientSecret", cfg.OAuth.ClientSecret),
-		zap.String("AuthURL", cfg.OAuth.AuthURL),
-		zap.String("TokenURL", cfg.OAuth.TokenURL),
-		zap.String("UserInfoURL", cfg.OAuth.UserInfoURL))
+	logger.Debug("Raw config loaded", zap.Any("config", cfg))
 
 	// Initialize OAuth2
 	oauthConfig = &oauth2.Config{
@@ -98,7 +162,7 @@ func main() {
 			AuthURL:  cfg.OAuth.AuthURL,
 			TokenURL: cfg.OAuth.TokenURL,
 		},
-		RedirectURL: fmt.Sprintf("http://localhost:%d/oauth/callback", cfg.Server.Port),
+		RedirectURL: fmt.Sprintf("http://localhost:3000/oauth/callback"),
 		Scopes:      []string{"profile", "email"},
 	}