diff --git a/build.gradle b/build.gradle
index f6fab35009a6f72fd446eedd67ad1cd73686f040..cb5f573cc10ea35ff24ce651c551df82c32873e7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -27,7 +27,8 @@ dependencies {
 	implementation 'org.springframework.boot:spring-boot-starter-web'
 	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
 	implementation 'org.mariadb.jdbc:mariadb-java-client:2.1.2'
-    testImplementation 'junit:junit:4.13.1'
+	implementation 'org.springframework.boot:spring-boot-starter-security'
+	testImplementation 'junit:junit:4.13.1'
     compileOnly 'org.projectlombok:lombok'
     testImplementation 'org.projectlombok:lombok:1.18.28'
     compileOnly 'org.projectlombok:lombok'
@@ -35,6 +36,8 @@ dependencies {
 	annotationProcessor 'org.projectlombok:lombok'
 	testImplementation 'org.springframework.boot:spring-boot-starter-test'
 	implementation 'org.springframework.boot:spring-boot-starter-validation'
+	implementation 'org.springframework.boot:spring-boot-starter-security'
+	implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.1.RELEASE'
 	// https://mvnrepository.com/artifact/org.webjars/openlayers
 	implementation group: 'org.webjars', name: 'openlayers', version: '5.2.0'
 }
@@ -42,6 +45,9 @@ dependencies {
 tasks.named('bootBuildImage') {
 	builder = 'paketobuildpacks/builder-jammy-base:latest'
 }
+test {
+	useJUnitPlatform()
+}
 
 tasks.named('test') {
 	useJUnitPlatform()
diff --git a/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java
index 65eaa9843ec3af33e994ea34ed8d219ce712ffaf..74c97a5f29319ab6dbefc042bcbc10e364b4bd03 100644
--- a/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java
+++ b/src/main/java/Team5/SmartTowns/rewards/RewardsRepositoryJDBC.java
@@ -10,7 +10,6 @@ import java.util.List;
 @Repository
 public class RewardsRepositoryJDBC implements RewardsRepository {
     private final JdbcTemplate jdbc;
-    private RowMapper<Badge> badgeMapper;
     private RowMapper<Sticker> stickerMapper;
     private RowMapper<Pack> packMapper;
 
@@ -51,8 +50,8 @@ public class RewardsRepositoryJDBC implements RewardsRepository {
 
     @Override
     public List<Sticker> getAllStickersFromPack(int packID){
-        String sql= "SELECT * FROM stickers WHERE packID="+packID;
-        return jdbc.query(sql, stickerMapper);
+        String sql= "SELECT * FROM stickers WHERE packID=?";
+        return jdbc.query(sql, stickerMapper, packID);
     }
 
     @Override
@@ -60,14 +59,14 @@ public class RewardsRepositoryJDBC implements RewardsRepository {
         /* FINDS ALL STICKERS UNLOCKED BY THE GIVEN USER */
         String sql= "SELECT * FROM stickers LEFT JOIN stickerprogress " +
                 "ON (stickers.id, stickers.packID) = (stickerprogress.stickerID, stickerprogress.packID) " +
-                "WHERE stickerprogress.userID="+userID;
-        return jdbc.query(sql, stickerMapper);
+                "WHERE stickerprogress.username = ? ";
+        return jdbc.query(sql, stickerMapper, userID);
     }
 
     @Override
     public Pack findPackByID(int id){
-        String sql= "SELECT * FROM packs WHERE id="+id;
-        List<Pack> result = jdbc.query(sql, packMapper);
+        String sql= "SELECT * FROM packs WHERE id= ?";
+        List<Pack> result = jdbc.query(sql, packMapper, id);
         return result.isEmpty() ? null : result.get(0);
     }
 }
diff --git a/src/main/java/Team5/SmartTowns/security/SecurityConfiguration.java b/src/main/java/Team5/SmartTowns/security/SecurityConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..afce617e22c6e82aa040896794e144ba0558ae37
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/security/SecurityConfiguration.java
@@ -0,0 +1,51 @@
+package Team5.SmartTowns.security;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.provisioning.JdbcUserDetailsManager;
+import org.springframework.security.provisioning.UserDetailsManager;
+import org.springframework.security.web.SecurityFilterChain;
+
+import javax.sql.DataSource;
+
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfiguration {
+    /* Configures the longin features and tracks logged on users on the page */
+
+
+    @Bean
+    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+        http
+                .authorizeHttpRequests((requests) -> requests
+                        .requestMatchers("/user/**", "/userProfile").authenticated()
+                        .anyRequest().permitAll()
+                )
+                .formLogin((login) -> login
+                        .loginPage("/login").permitAll()
+                        .defaultSuccessUrl("/userProfile")
+                )
+                .logout((logout) -> logout.permitAll());
+
+        return http.build();
+    }
+    @Bean
+    public PasswordEncoder passwordEncoder(){
+        /* Nothing here yet, this just saves passwords in plaintext. TODO password encryption */
+        return NoOpPasswordEncoder.getInstance();
+    }
+
+    @Bean
+    public UserDetailsManager userDetailsManager(DataSource dataSource){
+        JdbcUserDetailsManager manager = new JdbcUserDetailsManager(dataSource);
+        return manager;
+    }
+
+
+}
diff --git a/src/main/java/Team5/SmartTowns/users/NewUser.java b/src/main/java/Team5/SmartTowns/users/NewUser.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa47adac9931083fb0d199375e50032ce30ccd60
--- /dev/null
+++ b/src/main/java/Team5/SmartTowns/users/NewUser.java
@@ -0,0 +1,26 @@
+package Team5.SmartTowns.users;
+
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class NewUser {
+
+
+    @NotEmpty(message = "You must type in a username.")
+    @NotNull
+    String name;
+
+    @NotEmpty(message = "You must type in a password.")
+    @NotNull
+    String password;
+
+    @NotEmpty(message = "You must type in an email.")
+    @NotNull
+    String email;
+}
diff --git a/src/main/java/Team5/SmartTowns/users/User.java b/src/main/java/Team5/SmartTowns/users/User.java
index 4ef65c3b288f9433e37d60e8e984b869f3a8d53e..96949fb1b8543684407118138878b21db47826fe 100644
--- a/src/main/java/Team5/SmartTowns/users/User.java
+++ b/src/main/java/Team5/SmartTowns/users/User.java
@@ -27,8 +27,7 @@ public class User {
         this.dragonProgress = dragonProgress;
         imgPath = findImagePath();
     }
-    public User(int id, String email, String name) {
-        this.id = id;
+    public User(String email, String name) {
         this.email = email;
         this.name = name;
         imgPath = findImagePath();
diff --git a/src/main/java/Team5/SmartTowns/users/UserController.java b/src/main/java/Team5/SmartTowns/users/UserController.java
index 989d13b7161f783dc75bdcb9dbf379808b1584e4..e1acd4b66f1546db506ec5313c5680122e05587d 100644
--- a/src/main/java/Team5/SmartTowns/users/UserController.java
+++ b/src/main/java/Team5/SmartTowns/users/UserController.java
@@ -4,10 +4,15 @@ package Team5.SmartTowns.users;
 import Team5.SmartTowns.rewards.Pack;
 import Team5.SmartTowns.rewards.RewardsRepository;
 import Team5.SmartTowns.rewards.Sticker;
+import jakarta.validation.Valid;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
 import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.ui.Model;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.servlet.ModelAndView;
 
 import java.util.List;
@@ -17,45 +22,87 @@ public class UserController {
 
     @Autowired
     private UserRepository userRepository;
+
     @Autowired
     private RewardsRepository rewardsRepository;
 
+    /* LOGIN MAPPING & FUNCTIONS */
     @GetMapping("/login")
     public ModelAndView getLoginPage() {
         ModelAndView mav = new ModelAndView("users/login");
-//        List<User> users = userRepository.getAllUsers();
-//        mav.addObject("users", users);
+        mav.addObject("user", new NewUser( "", "", ""));
+        mav.addObject("error", "");
+        mav.addObject("status", "");
+        System.out.println(userRepository.findUserByName("Admin").getName());
         return mav;
     }
 
-    @GetMapping("/userList")
-    public ModelAndView userList() {
-        ModelAndView mav = new ModelAndView("towns/userData");
-        List<User> users = userRepository.getAllUsers();
-        mav.addObject("users", users);
+//    @GetMapping("/logout")
+//    public ModelAndView getLogOutPage(){
+//        ModelAndView mav = new ModelAndView("users/logout");
+//        return mav;
+//    }
+
+    @PostMapping("/login/register")
+    public ModelAndView registerUser(@Valid @ModelAttribute("user") NewUser user, BindingResult bindingResult, Model model) {
+        ModelAndView mav = new ModelAndView("users/login", model.asMap());
+        // TODO VALIDATE EMAIL INPUT
+        mav.addObject("status", "active");
+        if (bindingResult.hasErrors()) {
+            ModelAndView modelAndView = new ModelAndView("users/login");
+            modelAndView.addObject("errors", bindingResult);
+            return modelAndView;
+        }
+
+        if ( userRepository.doesUserExist(user.getEmail()) ) {
+            mav.addObject("errors", "Email already in use");
+            return mav;
+        }
+
+        try {
+            userRepository.addUser(user.name, user.email, user.password);
+            mav.addObject("error", "");
+            //TODO return user creation success
+            return mav;
+        } catch (DataAccessException e) {
+            mav.addObject("error", "User exists");
+        }
         return mav;
     }
 
-    @GetMapping("/user/{id}")
-    public ModelAndView getUserPage(@PathVariable int id) {
+    @GetMapping("/userProfile")
+    public ModelAndView userProfile(){
         ModelAndView mav = new ModelAndView("users/userProfile");
         List<Pack> allPacks = rewardsRepository.getAllPacks();
-        mav.addObject("user", userRepository.getUserById(id));
         mav.addObject("packs", allPacks);
 
-        mav.addAllObjects(getPackInfo(id, 1).getModelMap());
+        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        mav.addObject("user", userRepository.findUserByName("Admin"));
+        mav.addAllObjects(getPackInfo("Admin", 1).getModelMap());
+        return mav;
+    }
 
+
+    /* USER MAPPING & FUNCTIONS */
+    @GetMapping("/user/{username}")
+    public ModelAndView getUserPage(@PathVariable String username) {
+        ModelAndView mav = new ModelAndView("users/userProfile");
+        List<Pack> allPacks = rewardsRepository.getAllPacks();
+        mav.addObject("user", userRepository.findUserByName("Admin"));
+        mav.addObject("packs", allPacks);
+        mav.addAllObjects(getPackInfo(username, 1).getModelMap());
         return mav;
     }
 
-    @GetMapping("/packInfo/{userID}/{packID}")
-    public ModelAndView getPackInfo(@PathVariable int userID, @PathVariable int packID) {
+    @GetMapping("/packInfo/{username}/{packID}")
+    public ModelAndView getPackInfo(@PathVariable String username, @PathVariable int packID) {
         /* Displays on page the stickers present in the pack and colour the ones the
         *  user has acquired */
 
         ModelAndView mav = new ModelAndView("users/userFrags :: stickersBox");
         List<Sticker> allStickers = rewardsRepository.getAllStickersFromPack(packID);
-        List<Long> userStickers = userRepository.getUserStickersFromPack(userID, packID);
+        List<Long> userStickers = userRepository.getUserStickersFromPack(username, packID);
+        System.out.println(userStickers);
 
 
 
@@ -86,4 +133,7 @@ public class UserController {
         return displayedStickers;
     }
 
+
+
+
 }
diff --git a/src/main/java/Team5/SmartTowns/users/UserRepository.java b/src/main/java/Team5/SmartTowns/users/UserRepository.java
index f0f01269786128dd9afaa8d3becd5b3ada4944fa..097598e24dce331a62b34346c3ec2326fa215934 100644
--- a/src/main/java/Team5/SmartTowns/users/UserRepository.java
+++ b/src/main/java/Team5/SmartTowns/users/UserRepository.java
@@ -5,7 +5,10 @@ import java.util.List;
 
 public interface UserRepository {
     List<User> getAllUsers();
-    List<Long> getUserStickersFromPack(int userID, int packID);
-    User getUserById(int userID);
-    boolean unlockSticker(int userID, int packID, int stickerID);
+    List<Long> getUserStickersFromPack(String username, int packID);
+    boolean unlockSticker(String username, int packID, int stickerID);
+    boolean addUser(String username, String email, String password);
+    boolean doesUserExist(String email);
+    User findUserByEmail(String email);
+    User findUserByName(String name);
 }
diff --git a/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java
index 8b46fc3a568455e91c180b66fc91b65f20d20c81..a88ac6e1c91fc85e5eb19fb6f0f7fcef3b9cb833 100644
--- a/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java
+++ b/src/main/java/Team5/SmartTowns/users/UserRepositoryJDBC.java
@@ -1,16 +1,23 @@
 //Implements the users repository using JDBC
 package Team5.SmartTowns.users;
 
+import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.object.SqlQuery;
 import org.springframework.stereotype.Repository;
 
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Objects;
 
 @Repository
 public class UserRepositoryJDBC implements UserRepository{
-    private JdbcTemplate jdbc;
+    private final JdbcTemplate jdbc;
     private RowMapper<User> userMapper;
 
     public UserRepositoryJDBC(JdbcTemplate aJdbc){
@@ -20,9 +27,8 @@ public class UserRepositoryJDBC implements UserRepository{
 
     private void setUserMapper(){
         userMapper = (rs, i) -> new User(
-                rs.getInt("id"),
                 rs.getString("email"),
-                rs.getString("name")
+                rs.getString("username")
         );
     }
 
@@ -34,23 +40,57 @@ public class UserRepositoryJDBC implements UserRepository{
 
 
     @Override
-    public User getUserById(int userID){
-        String sql= "SELECT * FROM users WHERE id="+userID;
-        List<User> result = jdbc.query(sql, userMapper);
-        return result.isEmpty() ? null : result.get(0);
+    public List<Long> getUserStickersFromPack(String username, int packID) {
+        /* Returns a list with the stickerIDs of stickers that the specified user has unlocked from the given pack */
+        String sql = "SELECT stickerID FROM stickerprogress WHERE (username, packID)= (?,?)";
+        return jdbc.queryForList(sql, Long.class, username, packID);
     }
 
     @Override
-    public List<Long> getUserStickersFromPack(int userID, int packID) {
-        String sql = "SELECT stickerID FROM stickerprogress WHERE (userID, packID)= (" + userID + "," + packID + ")";
-        return jdbc.queryForList(sql, Long.class);
+    public boolean unlockSticker(String username, int packID, int stickerID){
+        /* Adds entry in the stickerprogress database, effectively unlocking the sticker for the user
+        *  Returns false if no sticker is unlocked */
+        String query = "SELECT COUNT(id) FROM stickers WHERE (stickerID, packID) = (?, ?)";
+
+        int stickerCount = jdbc.queryForObject(query, Integer.class, stickerID, packID);
+
+        if (stickerCount == 1){ //Checks if sticker exists
+            String sql = "INSERT INTO stickerprogress (username, packID, stickerID) VALUES (?,?,?)";
+            jdbc.update(sql, username, packID, stickerID);
+            return true;
+        }
+        return false;
     }
 
     @Override
-    public boolean unlockSticker(int userID, int packID, int stickerID){
-        String sql = "INSERT INTO stickerprogress (userID, packID, stickerID) VALUES (" +
-                userID + ", " + packID + "," + stickerID + ")";
-        jdbc.update(sql);
+    public boolean addUser(String username, String email, String password) throws DataAccessException{
+        /* Adds new user to the database */
+        String query = "INSERT INTO users (username, email, password) VALUES (?, ?, ?);";
+        String query2= "INSERT INTO authorities (username, authority) VALUES (?,?);";
+        jdbc.update(query, username, email, password);
+        jdbc.update(query2, username, "USER");
         return true;
     }
+    @Override
+    public boolean doesUserExist(String email){
+        /* Returns true if a user with given email already exists in the database */
+        String query = "SELECT COUNT(email) FROM users WHERE (email) = (?)";
+        return !(jdbc.queryForObject(query, Integer.class, email) == 0);
+    }
+
+    @Override
+    public User findUserByEmail(String email) {
+        /* Finds user matching given email */
+        String query = "SELECT * FROM users WHERE (email) = (?)";
+        List<User> result = jdbc.query(query, userMapper, email);
+        return result.isEmpty() ? null : result.get(0);
+    }
+    @Override
+    public User findUserByName(String name) {
+        /* Finds user matching given name */
+        String query = "SELECT * FROM users WHERE (username) = (?)";
+        List<User> result = jdbc.query(query, userMapper, name);
+        return result.isEmpty() ? null : result.get(0);
+    }
+
 }
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 95f46c69ab2c6b38e1c520a5b8438c8f87aba0a3..52e81d219c68d4702643665e6f9d58c7aebb8308 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -3,3 +3,4 @@ spring.datasource.username=root
 spring.datasource.password=comsc
 
 spring.sql.init.mode=always
+spring.sql.init.data-locations=classpath:data.sql, classpath:/static/sql/user-data.sql, classpath:/static/sql/user-progress-data.sql
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
new file mode 100644
index 0000000000000000000000000000000000000000..b91b4f71db6b6d4005596c17a8c75a2a9f178d34
--- /dev/null
+++ b/src/main/resources/data.sql
@@ -0,0 +1,52 @@
+delete from trails;
+insert into trails ( Name,tru) value ( 'Caerphilly Coffee Trail',false);
+insert into trails ( Name,tru) value ( 'Penarth Dragon Trail',true);
+
+delete from locations;
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'St Cenydd','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Castle','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Medieval Trades','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Queen''s War','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Green Lady','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Armoury','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Architecture','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( '21st Century Landmark','','Location description here','Caerphilly',0101, true);
+
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'JD Wetherspoons-Malcolm Uphill','','Location description here','Caerphilly',0102, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Cwtch','','Location description here','Caerphilly',0102, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Conservative Club','','Location description here','Caerphilly',0102, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The King''s Arms','','Location description here','Caerphilly',0102, true);
+
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Bus Station','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Medieval Courthouse','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ('Caerphilly Castle','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Ty Vaughan House','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Risca Colliery','','Location description here','Risca',0201, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Black Vein Colliery Disaster','','Location description here','Risca',0201, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Esplanade','','Location description here','Penarth',0301, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Old Swimming Baths','','Location description here','Penarth',0301, true);
+
+
+
+
+
+DELETE FROM packs;
+INSERT INTO packs (name, description) VALUE ('Wales Football Team', 'Pack of Welsh Football Players in the National Team');
+INSERT INTO packs (name, description) VALUE ('Wales Rugby Team', 'Pack of Welsh Rugby Players in the National Team');
+INSERT INTO packs (name, description) VALUE ('Welsh Heritage', 'Pack About Welsh Heritage');
+
+DELETE FROM stickers;
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 1, 'wayne_hennessey', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 2, 'neco_williams', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 3, 'joe_morrell', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 4, 'ethan_ampadu', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 5, 'connor_roberts', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 1, 'Taine_Basham', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 2, 'Adam Beard', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 3, 'Elliot Dee', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 4, 'Corey Domachowski', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 5, 'Ryan Elias', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 1, 'Welsh Lady', 'Welsh Heritage', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 2, 'Welsh Outline', 'Welsh Heritage', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 3, 'Welsh Spoon', 'Welsh Heritage', '1');
+
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..403c5bf4ba23873ea9d6e8da956823c5830d2353
--- /dev/null
+++ b/src/main/resources/schema.sql
@@ -0,0 +1,113 @@
+/* DELETES AND RECREATES DATABASE EVERY TIME THE SYSTEM IS BOOTED*/
+DROP DATABASE IF EXISTS towns;
+CREATE DATABASE IF NOT EXISTS towns;
+USE towns;
+/****************************************************************/
+
+/* DROPS ALL TABLES IF THEY EXIST (they wont but just in case) */
+DROP TABLE IF EXISTS trails;
+DROP TABLE IF EXISTS locations;
+DROP TABLE IF EXISTS users;
+DROP TABLE IF EXISTS stickers;
+DROP TABLE IF EXISTS packs;
+DROP TABLE IF EXISTS stickerProgress;
+/****************************************************************/
+
+/* CREATES ALL TABLES */
+
+CREATE TABLE IF NOT EXISTS trails (
+    trailID bigint auto_increment primary key,
+    name varchar(128),
+    tru boolean
+)   engine=InnoDB;
+
+drop table if exists locationCoordinates;
+drop table if exists locations;
+create table if not exists locations
+(
+    locationID bigint auto_increment primary key,
+    locationName varchar(128),
+    locationEmail varchar(128),
+    locationDescription longtext,
+    locationPlace varchar(255),
+    locationTrailID varchar(128),
+    locationApproved boolean
+)   engine=InnoDB;
+
+
+CREATE TABLE IF NOT EXISTS users (
+    username varchar(30) primary key NOT NULL,
+    id bigint auto_increment unique, /*DEPRECATED COLUMN, LEFT IN WHILE SOME OTHER FUNCTIONS STILL USE IT*/
+    email varchar(128),
+    password varchar(30) NOT NULL,
+    enabled boolean default true
+);
+
+CREATE TABLE IF NOT EXISTS authorities (
+    id bigint primary key auto_increment NOT NULL,
+    username varchar(30) NOT NULL ,
+    authority varchar(45) NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS packs (
+    id bigint auto_increment primary key,
+    name varchar(20) NOT NULL,
+    description text
+);
+
+CREATE TABLE IF NOT EXISTS stickers (
+    id bigint auto_increment primary key,
+    packID bigint NOT NULL,
+    FOREIGN KEY (packID) REFERENCES packs(id)
+        ON DELETE CASCADE
+        ON UPDATE RESTRICT,
+    stickerID bigint NOT NULL, /*STICKER ID NUMBER WITHIN ITS OWN PACK*/
+    name varchar(30) NOT NULL,
+    description text NOT NULL,
+    rarity tinyint
+);
+
+CREATE TABLE IF NOT EXISTS stickerProgress (
+    id bigint auto_increment primary key,
+    username varchar(30) NOT NULL,
+    FOREIGN KEY (username) REFERENCES users(username)
+        ON DELETE CASCADE
+        ON UPDATE RESTRICT,
+    packID bigint NOT NULL,
+    FOREIGN KEY (packID) REFERENCES packs(id)
+        ON DELETE CASCADE
+        ON UPDATE RESTRICT,
+    stickerID bigint NOT NULL,
+        FOREIGN KEY (stickerID) REFERENCES stickers(id)
+        ON DELETE CASCADE
+        ON UPDATE RESTRICT
+);
+
+create table if not exists locationCoordinates
+(
+    locationCoordID bigint auto_increment primary key,
+    locationID bigint,
+    Foreign Key (locationID) REFERENCES locations(locationID)
+        ON DELETE CASCADE
+        ON UPDATE RESTRICT,
+    locationCoordsLat DECIMAL(8,6),
+    locationCoordsLong DECIMAL(8,6)
+
+
+)engine=InnoDB;
+
+
+drop table if exists townsWithTrails;
+create table if not exists townsWithTrails
+(
+    townID bigint auto_increment primary key,
+    townName varchar(128),
+    townCentreCoordsLat varchar(128),
+    townCentreCoordsLong varchar(128),
+    townUppermostCoordsLat varchar(128),
+    townLowermostCoordsLat varchar(128),
+    townLeftmostCoordsLong varchar(128),
+    townRightmostCoordsLong varchar(128)
+
+)engine=InnoDB;
+
diff --git a/src/main/resources/static/css/login.css b/src/main/resources/static/css/login.css
new file mode 100644
index 0000000000000000000000000000000000000000..023566c253e9354e789e85744cd1e4989d523845
--- /dev/null
+++ b/src/main/resources/static/css/login.css
@@ -0,0 +1,372 @@
+@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap');
+
+:root {
+    --container-colour: #2a2a2a;
+    --details-colour: var(--primary-light);
+    --details-light: #512da8;
+
+    --font-buttons: 14px;
+    --font-size-1: 14px;
+    --font-size-2: 200px;
+    --font-size-3: 300px;
+
+    --error-colour: red;
+}
+
+*{
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+    font-family: 'Montserrat', sans-serif;
+    color: white;
+}
+
+body{
+    align-items: center;
+    height: 100svh;
+}
+
+main {
+    height: 90%;
+    width: 90%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+@keyframes move{
+    0%, 49.99%{
+        opacity: 0;
+        z-index: 1;
+    }
+    50%, 100%{
+        opacity: 1;
+        z-index: 5;
+    }
+}
+
+@media only screen
+and (min-device-width: 650px) {
+    .container{
+        background-color: var(--container-colour);
+        border-radius: 30px;
+        box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35);
+        position: relative;
+        overflow: hidden;
+        min-width: 768px;
+        max-width: 100%;
+        min-height: 480px;
+    }
+
+    .container p{
+        font-size: 14px;
+        line-height: 20px;
+        letter-spacing: 0.3px;
+        margin: 20px 0;
+    }
+
+
+    .container a{
+        font-size: var(--font-size-1);
+        text-decoration: none;
+        margin: 15px 0 10px;
+    }
+
+    .container button{
+        background-color: var(--details-colour)/*#512da8*/;
+        color: #fff;
+        font-size: var(--font-buttons);
+        padding: 10px 45px;
+        border: 1px solid transparent;
+        border-radius: 8px;
+        font-weight: 600;
+        letter-spacing: 0.5px;
+        text-transform: uppercase;
+        margin-top: 10px;
+        cursor: pointer;
+    }
+
+    .container button.hidden{
+        background-color: transparent;
+        border-color: #fff;
+    }
+
+    .container form{
+        background-color: var(--container-colour);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        flex-direction: column;
+        padding: 0 40px;
+        height: 100%;
+    }
+
+    .container input{
+        background-color: #eee;
+        border: none;
+        margin: 8px 0;
+        padding: 10px 15px;
+        font-size: 13px;
+        border-radius: 8px;
+        width: 100%;
+        outline: none;
+    }
+
+    .form-container{
+        position: absolute;
+        top: 0;
+        height: 100%;
+        transition: all 0.6s ease-in-out;
+    }
+
+    .sign-in{
+        left: 0;
+        width: 50%;
+        z-index: 2;
+    }
+
+    .container.active .sign-in{
+        transform: translateX(100%);
+    }
+
+    .sign-up{
+        left: 0;
+        width: 50%;
+        opacity: 0;
+        z-index: 1;
+    }
+
+    .container.active .sign-up{
+        transform: translateX(100%);
+        opacity: 1;
+        z-index: 5;
+        animation: move 0.6s;
+    }
+
+
+
+    .toggle-container{
+        position: absolute;
+        top: 0;
+        left: 50%;
+        width: 50%;
+        height: 100%;
+        overflow: hidden;
+        transition: all 0.6s ease-in-out;
+        border-radius: 150px 0 0 100px;
+        z-index: 1000;
+    }
+
+    .container.active .toggle-container{
+        transform: translateX(-100%); /*BG THING*/
+        border-radius: 0 150px 100px 0;
+    }
+
+    .toggle{
+        background-color: var(--details-colour);
+        height: 100%;
+        background: linear-gradient(to right, var(--details-light), var(--details-colour));
+        color: #fff;
+        position: relative;
+        left: -100%;
+        height: 100%;
+        width: 200%;
+        transform: translateX(0);
+        transition: all 0.6s ease-in-out;
+    }
+
+    .container.active .toggle{
+        transform: translateX(50%);
+    }
+
+    .toggle-panel{
+        position: absolute;
+        width: 50%;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        flex-direction: column;
+        padding: 0 30px;
+        text-align: center;
+        top: 0;
+        transform: translateX(0);
+        transition: all 0.6s ease-in-out;
+    }
+
+    .toggle-left{
+        transform: translateX(-200%);
+    }
+
+    .container.active .toggle-left{
+        transform: translateX(0);
+    }
+
+    .toggle-right{
+        right: 0;
+        transform: translateX(0);
+    }
+
+    .container.active .toggle-right{
+        transform: translateX(200%);
+    }
+    .input {
+        color: black;
+    }
+
+}
+@media only screen
+and (max-device-width: 640px) {
+    .container {
+        position: relative;
+
+        background-color: var(--container-colour);
+        border-radius: 30px;
+        box-shadow: 0 5px 15px rgba(0, 0, 0, 0.35);
+
+        overflow: hidden;
+
+        width: 100%;
+        height: 100%;
+
+        display: flex;
+        flex-direction: column;
+        justify-content: space-evenly;
+    }
+    .form-container {
+        height: 100%;
+        transition: all 0.6s ease-in-out;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+    }
+    .form-container form {
+        display: flex;
+
+        flex-direction: column;
+        align-items: center;
+        font-size: 3em;
+        margin-inline: 5%;
+    }
+    .form-container input {
+        flex: 1 1;
+        font-size: 1em;
+        color: black;
+        margin-block: 5%;
+        padding: 2%;
+        border-radius: 30px;
+    }
+
+    .form-container button {
+        flex: 1 1;
+        font-size: 1em;
+    }
+    .toggle-container {
+        position: absolute;
+        top: 0;
+        width: 100%;
+        height: 50%;
+        transition: all 0.6s ease-in-out;
+        overflow: hidden;
+        border-radius:  0 0 150px 150px;
+        z-index: 1000;
+
+    }
+    .container.active .toggle-container{
+        transform: translateY(100%); /*BG THING*/
+        border-radius: 150px 150px 0 0;
+    }
+    .toggle {
+        position: absolute;
+        width: 100%;
+        height: 200%;
+        display: flex;
+        flex-direction: column-reverse;
+        align-items: center;
+        justify-content: space-evenly;
+        background: linear-gradient(to bottom, var(--details-light), var(--details-colour));
+        /*background-color: red;*/
+    }
+    .toggle-panel {
+        flex: 1 1;
+        width: 100%;
+    }
+    .container .toggle-right {
+        transform: translateY(0);
+        opacity: 1;
+    }
+    .container .toggle-left {
+        transform: translateY(-100%);
+        opacity: 0;
+    }
+    .container.active .toggle-right{
+        transform: translateY(-100%);
+        opacity: 0;
+    }
+    .container.active .toggle-left{
+        transform: translateY(-100%);
+        opacity: 1;
+    }
+
+    .container .sign-up {
+        opacity: 0;
+        z-index: -1;
+        transform: translateY(100%);
+    }
+    .container .sign-in {
+        opacity: 1;
+        z-index: 5;
+    }
+
+    .container.active .sign-in{
+        transform: translateY(-100%);
+        opacity: 0;
+        z-index: -1;
+    }
+    .container.active .sign-up{
+        animation: move 0.6s;
+        opacity: 1;
+        z-index: 5;
+        transform: translateY(0);
+    }
+
+
+    .toggle-panel {
+        transition: all 0.6s ease-in-out;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        font-size: xxx-large;
+
+    }
+    .toggle-panel p {
+        margin-inline: 10%;
+        margin-block: 5%;
+        line-height: 1.5em;
+    }
+    .container button{
+        background-color: var(--details-colour)/*#512da8*/;
+        color: #fff;
+        font-size: xxx-large;
+        padding: 40px 40px;
+        border: 5px solid transparent;
+        border-radius: 14px;
+        font-weight: 600;
+        letter-spacing: 1px;
+        text-transform: uppercase;
+        margin-top: 30px;
+        cursor: pointer;
+    }
+
+    .container button.hidden{
+        background-color: transparent;
+        border-color: #fff;
+    }
+}
+.alert {
+    color: var(--error-colour);
+    text-shadow: var(--error-colour) 0 0 10px;
+}
+
diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css
index 08273bc1bba5a74c518361f71f7d88bb53774811..934cac13d9ed4bfebab932cc72b6839e0869b25b 100644
--- a/src/main/resources/static/css/style.css
+++ b/src/main/resources/static/css/style.css
@@ -1,210 +1,87 @@
 * {
-   box-sizing: border-box;
-   padding: 0;
-   margin: 0;
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
 }
 
-#homeHead{
-    color: inherit;
-    text-decoration: none;
-    padding: 0;
-    margin: 0;}
+* {
+    /*COLOUR PALETTE*/
+    @media (prefers-color-scheme: dark) {
+        --primary-darker: hsl(272, 100%, 10%);
+        --primary-dark: hsl(271, 100%, 20%);
+        --primary-colour: hsl(271, 100%, 30%);
+        --primary-light: hsl(271, 100%, 40%);
+        --primary-lighter: hsl(271, 100%, 50%);
+
+        --secondary-colour: hsl(12, 81%, 46%);
+        --accent-colour: hsl(12, 82%, 32%);
+        --accent-border: hsl(12, 81%, 25%);
+
+        --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em;
+
+        color:  white;
 
-.center {
-    text-align: center;
-}
-body {
-    background-color: rgb(41, 41, 41);
-    margin: 0%;
-}
-.headerBlock {
-    background-color: rgb(15, 15, 15);
-    padding-bottom: 20px;
-    box-shadow: 0 10px 20px black;
-    .headerTitle {
-        text-align: center;
-        padding: 10px 10px 0 10px;
-        margin: 0 50px 0 50px;    
-        letter-spacing: 10px;
-        font-size: 50px;
-        font-style: italic;
-        color: blueviolet;
-        text-shadow: black 3px 3px 5px;
-        border-bottom: 3px blueviolet solid;
-    }
-    .headerBanner {
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-        overflow: hidden;
-        position: relative;
-        height: 200px;
-        border-top: grey solid 2px;
-        border-bottom: grey solid 2px;
-
-        .bannerBack {
-            opacity: 0.6;
-            width: 100%;
-            left: 0;
-            top: 0;
-            position: absolute
-        }
-        .bigTitle {
-            color:white;
-            text-align: center;
-            position: relative;
-            font-size: 50px;
-            margin: 20px 20px 5px;
-        }
-        .smallTitle {
-            position: relative;
-            color:white;
-            text-align: center;
-            font-size: 20px;
-            margin: 5px 20px 20px;
-        }
     }
-}
+    @media (prefers-color-scheme: light) {
+        --primary-darker: hsl(272, 100%, 10%);
+        --primary-dark: hsl(271, 100%, 20%);
+        --primary-colour: hsl(271, 100%, 30%);
+        --primary-light: hsl(271, 100%, 40%);
+        --primary-lighter: hsl(271, 100%, 50%);
 
+        --secondary-colour: hsl(12, 81%, 46%);
+        --accent-colour: hsl(12, 82%, 32%);
+        --accent-border: hsl(12, 81%, 25%);
+
+        --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em;
+
+        color: white;
 
 
-.mainTrails{
-    overflow: hidden;
-    position: relative;
-    height: 200px;
-    border-top: grey solid 2px;
-    border-bottom: grey solid 2px;
-}
-.trailList {
-    .ulHeader {
-        margin: 30px;
-        display: flex;
-        list-style: none;
-        justify-content: center;
-        padding: 0px;
-        border-bottom: solid black 5px;
-
-        .liHeader {
-            
-            flex: 1 1 0px;
-            padding-left: 10px;
-            padding-right: 10px;
-            color: white;
-            text-align: center;
-        }
-        .liHeader:hover {
-            color: blueviolet;
-            border-bottom: solid blueviolet 2px;  
-        }
-        .selected {
-            flex: 1 1 0px;
-            padding-left: 10px;
-            padding-right: 10px;
-            color: rgb(154, 69, 234);
-            border-bottom: solid blueviolet 2px;
-            text-align: center;
-        }
     }
-    
 }
-.mainBlock {
+
+body {
+    background: linear-gradient(to bottom right,
+    var(--primary-darker),
+    var(--primary-dark),
+    var(--primary-darker));
+
     display: flex;
-    min-width: 300px;
-    flex-wrap: wrap;
-    margin-top: 20px;
-    margin-bottom: 100px;
+    flex-direction: column;
+    justify-content: center;
+    align-content: center;
 }
-.mainBlock .trailStats{
-    background-color: rgb(206, 153, 253);
-    flex: 0 0 0px;
-    min-width: 400px;
-    height: 600px;
-    margin: auto;
-    margin-bottom: 20px;
-    box-shadow: 0px 0px 20px rgb(20, 20, 20);
-    border-radius: 30px;
-    .stats {
-        display: block;
-        width: 200px;
-        margin: auto;
-    }
-    .textStats {
-        display: block;
-        text-align: left;
-        margin: 20px;
-    }
-}
-.mainBlock .trailInfo{
-    background-color: rgb(206, 153, 253);
-    flex: 0 0 0px;
-    min-width: 400px;
-    height: 600px;
-    margin: auto;
-    margin-bottom: 20px;
-    box-shadow: 0px 10px 10px rgb(20, 20, 20);
-    border-radius: 30px;
-    .trailInfoTxt {
-        margin: 15px;
-    }
-}
-.titleH1 {
-    padding: 0px;
-    margin: 10px 30px 20px 30px;
-    text-align: center;
-    font-size: 40px;
-    font-style: italic;
-    border-bottom: solid black 1px;
-}
-.mainBlock p {
-    font-size: 25px;
-    text-align: left;
-    padding: 1px;
-}
-main .badgesBlock{
-    bottom: 0%;
-    background-color: rgb(222, 75, 255);
-    flex: 0 0 0px;
-    min-width: 500px;
-    min-height: 100px;
-    margin: auto;
-    margin-bottom: 10px;
-    box-shadow: 0px 10px 10px rgb(20, 20, 20);
-    border-radius: 30px;
-}
-.badgesList {
+.centerAll {
     display: flex;
-}
-.badgeImg {
-    flex: 0 1 0px;
-    width: 60px;
-    margin: auto;
-    margin-bottom: 20px;
-    
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
 }
 
-footer {
-    z-index: 99;
-    bottom: 0%;
-    left: 0%;
-    position: fixed;
-    width: 100%;
-    min-width: 300px;
-}
-footer .footerBar {
-    display: flex;
-    list-style: none;
-    padding: 0;
-    margin: 0;
-    
+/*PHONES PORTRAIT*/
+@media only screen
+and (min-device-width: 320px)
+and (max-device-width: 640px) {
+    body {
+        position: fixed;
+        width: 100vw;
+        height: 100svh;
+    }
+    html {
+        position: fixed;
+        width: 100vw;
+        height: 100svh;
+    }
 }
-footer .footerButton {
-    padding: 20px;
-    text-align: center;
-    flex: 1 1 0px;
-    color:crimson;
-    background-color: white;
-    
+
+/*PHONES LANDSCAPE*/
+@media only screen
+and (min-device-width: 640px)
+and (max-device-width: 1000px) {
+
+
 }
-footer .footerButton:hover {
-    background-color: black;
-}
\ No newline at end of file
+
+/*LARGER SCREENS*/
+@media only screen and (min-device-width: 1000px) {}
\ No newline at end of file
diff --git a/src/main/resources/static/css/userProfile.css b/src/main/resources/static/css/userProfile.css
deleted file mode 100644
index 878ab054fc53828cb76726775109ca7d3f4bcc80..0000000000000000000000000000000000000000
--- a/src/main/resources/static/css/userProfile.css
+++ /dev/null
@@ -1,408 +0,0 @@
-/* AUTHOR: Gabriel Copat*/
-@import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap');
-@import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap');
-
-/*COLOUR PALETTE*/
-* {
-    --main-colour: #e47201;
-    --secondary-colour: #e47201;
-    --accent-colour: #e47201;
-    --accent-border: #b25901;
-
-    --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em;
-}
-
-
-/*FONTS, TYPOGRAPHY & BACKGROUNDS*/
-* {
-    margin: 0;
-    padding: 0;
-
-    & h1, & h2 {
-        letter-spacing: 0.25vw;
-        line-height: 1.3;
-        text-align: center;
-        color: white;
-        text-justify: inter-word;
-    }
-    & label {
-        color: white;
-    }
-
-}
-@media only screen and (max-device-width: 500px) {
-    /*ADJUSTING FOR SMALLER SCREENS*/
-    * {
-        & h1, & h2 { text-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1svh;}
-        & p { line-height: 1.1; color: white;}
-    }
-}
-html{
-    height: 100%;
-    @media only screen and (min-device-width: 1500px) {
-        height: auto;
-    }
-}
-body {
-    background: linear-gradient(135deg, #f7e8fd, #9914d1);
-    height: 100%;
-    display: flex;
-    flex-direction: column;
-    justify-content: space-evenly;
-    @media only screen and (min-device-width: 1500px) {
-        height: auto;
-    }
-}
-main {
-    background: linear-gradient(to bottom, #1e1e1e 10%, darkgoldenrod 50%, #1e1e1e 90%);
-    border-radius: 1vw;
-    margin-inline: 5%;
-    /*margin-block: 5%;*/
-    width: auto;
-    padding-block: 2svh;
-    margin-top: 6em;
-    padding-inline: 1vw;
-    box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em);
-    transition: all linear 2s;
-    overflow-y: scroll;
-    height: 90%;
-    @media only screen and (min-device-width: 1500px) {
-        padding-inline: 20%;
-        overflow: visible;
-    }
-}
-.rewards {
-    position: relative;
-}
-.userInfo {
-    display: flex;
-    flex-direction: column;
-    /*padding: min(2vw, 4em);*/
-    text-align: center;
-
-    & #userPicture {
-        width: min(30vw, 30em);
-        margin-inline: auto;
-        border-radius: 100%;
-        border: solid #a2a2a2 4px;
-        box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em);
-    }
-
-    & h1 {
-        font-size: max(5vw, 2em);
-        margin: 1svh 25%;
-        color:white;
-        border-bottom: #36454F solid 2px;
-        border-radius: 5vw;
-        box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1vw -1vw;
-    }
-}
-#packsBar::-webkit-scrollbar {
-    display: none;
-    -ms-scrollbar-darkshadow-color: transparent;
-}
-#packsBar {
-    position: static;
-    display: grid;
-    grid-template-areas:
-        "header"
-        "packs";
-    overflow-x: scroll;
-    overflow-y: hidden;
-    color: white;
-    padding-bottom: 2%;
-    @media only screen and (min-device-width: 501px) {
-        height: 24vw;
-    }
-    & h2 {
-        position: absolute;
-        grid-area: header;
-        margin-inline: 5vw;
-        padding-inline: 2vw;
-        margin-block: -1svh;
-        box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh 1vw -1vw;
-        border-bottom: #36454F solid 2px;
-        font-size: 4vw;
-        width: 7em;
-        height: 1.2em;
-
-    }
-    & #allPacksContainer {
-        margin-top: 3svh;
-        grid-area: packs;
-        height: 12svh;
-        width: 100%;
-        display: flex;
-        justify-content: space-between;
-        @media only screen and (min-device-width: 501px) {
-            height: 20vw;
-            margin-top: 6vw;
-        }
-    }
-    & .packContainer{
-        position: relative;
-        height: 12svh;
-        width: 20vw;
-        display: flex;
-        flex-direction: column;
-        text-align: center;
-        justify-content: center;
-        overflow: visible;
-    }
-
-    & .packImg {
-        position: relative;
-        margin-inline: 3vw;
-        height: 8svh;
-        /*width: 25%;*/
-        z-index: 50;
-        @media only screen and (min-device-width: 501px) {
-            height: 15vw;
-        }
-        transition: 0.3s ease-out 100ms;
-    }
-    & .packImg:hover {
-        /*box-shadow: 0 0 20px 10px #bbbb00;*/
-        transform: scale(1.5,1.5);
-
-    }
-    & .packName {
-        height: 4svh;
-        display: flex;
-        justify-content: center;
-        font-size: 2em;
-        overflow: hidden;
-        align-items: flex-end;
-
-    }
-}
-
-#stickersBox {
-    padding-top: 5%;
-    display: flex;
-    flex-direction: column;
-    /* border-bottom-left-radius: 2vw; */
-    /* border-bottom-right-radius: 2vw; */
-    /*background: linear-gradient(to bottom, darkgoldenrod, transparent 90%);*/
-    margin-top: -1%;
-    height: 500px;
-    & h2 {
-        font-size: 4em;
-        text-align: center;
-        box-shadow: rgba(0, 0, 0, 0.7) 0 2vw 2vw -2vw;
-        border-bottom: #36454F solid 2px;
-        margin-block: 1svh;
-        margin-inline: 25%;
-    }
-    & .stickersContainer {
-        margin-block: 1svh;
-        display: flex;
-        flex-wrap: wrap;
-        justify-content: space-around;
-        width: 100%;
-
-        & .stickerImg {
-            width: 20vw;
-            margin-block: 1em;
-
-        }
-    }
-}
-.locked {
-    filter: grayscale(100%);
-}
-
-.dragonProgression {
-    position: relative;
-    display: flex;
-    flex-direction: column;
-    justify-content: center;
-    text-align: center;
-    height: 16svh;
-    box-sizing: content-box;
-    /*background: linear-gradient(to bottom, transparent -50%, darkgoldenrod 50%);*/
-    width: 100%;
-    /*padding-top: 1svh;*/
-
-    @media only screen and (min-device-width: 501px) {
-        height: 28vw;
-        margin-bottom: 0;
-        padding-bottom: 5svh;
-    }
-    & h1 {
-        font-size: 3em;
-        font-family: 'MedievalSharp', cursive;
-        letter-spacing: 1vw;
-        box-shadow: rgba(0, 0, 0, 0.7) 0 2vw 2vw -2vw;
-        border-bottom: #36454F solid 2px;
-        border-top: #36454F solid 2px;
-        margin-inline: 15%;
-        margin-bottom: 1%;
-    }
-    & .dragonContainer {
-        position: relative;
-        margin: auto;
-    }
-    & .dragonImg {
-        height: 10svh;
-        width: 16svh;
-        @media only screen and (min-device-width: 501px) {
-            height: 22vw;
-            width: 30vw;
-        }
-
-    }
-    & .dragonFill {
-        position: absolute;
-        overflow: hidden;
-        width: 40%;
-    }
-    & .dragonOut {
-        /*position: absolute;*/
-        overflow: hidden;
-    }
-}
-header {
-    z-index: 99;
-    top: 0.5svh;
-    left: 0;
-    position: fixed;
-    width: 100vw;
-    justify-content: center;
-    display: flex;
-}
-header .footerBar {
-    display: flex;
-    list-style: none;
-    border-radius: 1vw;
-    overflow: hidden;
-    justify-content: space-evenly;
-    background-color: rgba(0, 0, 0, 0.7);
-}
-header .footerButton {
-    padding: 1vw;
-    text-align: center;
-    /*flex: 1 1;*/
-    color:crimson;
-    background-color: rgba(31, 31, 31, 0.7);
-    font-size: 2.5em;
-    width: 15vw;
-}
-header .footerButton:hover {
-    background-color: #36454F;
-}
-
-.grayedOut {
-    filter: grayscale(1);
-}
-
-.solidBg {
-    background: #1e1e1e;
-    display: flex;
-}
-.loginWrapper {
-    margin-inline: auto;
-    margin-block: 5svh;
-    display: flex;
-    text-align: center;
-    justify-content: center;
-    background: rgba(196, 92, 239, 0.75);
-    padding: 2em;
-    flex: 0 0;
-    border-radius: 1vw;
-    box-shadow: rgba(0, 0, 0, 0.7) 0 0.5svh max(1vw, 1em);
-    & h2 {
-        margin-left: 0;
-        margin-right: auto;
-        margin-bottom: 0.5em;
-    }
-    & form{
-        margin-block: auto;
-        font-size: 3em;
-        display: flex;
-        flex-direction: column;
-    }
-    & label {
-        position: relative;
-        margin-top: 1em;
-        /*width: fit-content;*/
-        font-size: 0.8em;
-        & b {
-            float: left;
-        }
-        & a {
-            position: absolute;
-            font-size: 0.4em;
-            right: 0.2em;
-            bottom: 0.2em;
-            height: fit-content;
-        }
-
-    }
-    & input {
-        font-size: 0.6em;
-        height: 1.5em;
-        width: 40vw;
-        border-radius: 0.2em;
-        padding-inline: 0.4em;
-        border: transparent solid 0.1em;
-        margin-bottom: 1em;
-    }
-    & button {
-        font-size: 1em;
-        height: 2em;
-        width: 4em;
-        box-shadow: var(--accent-shadow);
-        margin:auto;
-        margin-top: 1em;
-        background-color: var(--accent-colour);
-        border: 0.1em solid var(--accent-border);
-        border-radius: 1em;
-        color: white;
-
-    }
-    & button:hover{
-        background-color: var(--accent-border);
-        border: 0.1em solid var(--accent-colour);
-    }
-}
-.label {
-    position: relative;
-}
-.invalid-tooltip {
-    color: red;
-    width: fit-content;
-    opacity: 0;
-    font-size: 0.6em;
-    text-shadow: red 0 0.2em 1em;
-    transition: 0.3s ease-in-out 1ms;
-    padding:0.1em;
-    position: absolute;
-    right: 0.2em;
-    bottom: 0.2em;
-    height: fit-content;
-}
-.invalid-field {
-    box-shadow: red 0 0 1em;
-    transition: 0.3s ease-in-out 1ms;
-}
-.valid-field {
-    box-shadow: #40ff00 0 0 1em;
-    border: #40ff00 solid 0.1em;
-    transition: 0.3s ease-in-out 1ms;
-}
-
-
-#invalidLogin {
-    color: red;
-    text-shadow: black 0 0.1em 0.2em;
-    width: auto;
-    height: auto;
-    font-size: 0.6em;
-    opacity: 0;
-    transition: 0.5s ease-in-out 1ms;
-}
-
-.rewards {
-    transition: 1s ease-in-out 1ms;
-}
\ No newline at end of file
diff --git a/src/main/resources/static/css/userProfile2.css b/src/main/resources/static/css/userProfile2.css
index 0728cbc6e973473051420fd817d243d5d484c489..0c5c0e9c4aef739bda2f4d38039fa4735a3e30bb 100644
--- a/src/main/resources/static/css/userProfile2.css
+++ b/src/main/resources/static/css/userProfile2.css
@@ -2,46 +2,7 @@
 @import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap');
 @import url('https://fonts.googleapis.com/css2?family=MedievalSharp&display=swap');
 
-* {
-    margin: 0;
-    padding: 0;
-    box-sizing: border-box;
 
-    /*COLOUR PALETTE*/
-    @media (prefers-color-scheme: dark) {
-        --primary-darker: hsl(272, 100%, 10%);
-        --primary-dark: hsl(271, 100%, 20%);
-        --primary-colour: hsl(271, 100%, 30%);
-        --primary-light: hsl(271, 100%, 40%);
-        --primary-lighter: hsl(271, 100%, 50%);
-
-        --secondary-colour: hsl(12, 81%, 46%);
-        --accent-colour: hsl(12, 82%, 32%);
-        --accent-border: hsl(12, 81%, 25%);
-
-        --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em;
-
-        color: white;
-
-    }
-    @media (prefers-color-scheme: light) {
-        --primary-darker: hsl(272, 100%, 10%);
-        --primary-dark: hsl(271, 100%, 20%);
-        --primary-colour: hsl(271, 100%, 30%);
-        --primary-light: hsl(271, 100%, 40%);
-        --primary-lighter: hsl(271, 100%, 50%);
-
-        --secondary-colour: hsl(12, 81%, 46%);
-        --accent-colour: hsl(12, 82%, 32%);
-        --accent-border: hsl(12, 81%, 25%);
-
-        --accent-shadow: rgba(0, 0, 0, 0.7) 0 0.5em 1em -0.5em;
-
-        color: white;
-
-
-    }
-}
 
 
 
@@ -237,8 +198,14 @@ main {
     height: 17em;
     margin: 1.5em;
 }
-/*}*/
+/* LOGIN FORM PAGE */
+
 
+
+
+
+
+/* MEDIA TYPE UPDATES*/
 @media only screen
 and (min-device-width: 320px)
 and (max-device-width: 640px) {
@@ -306,4 +273,21 @@ and (min-device-width: 1000px) {
     .progressionContainer {
         height: 20svh;
     }
-}
\ No newline at end of file
+}
+
+.container {
+    width: 500px;
+    margin-block: 5%;
+    background-color: var(--accent-colour);
+    border-radius: 10em;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    & form {
+        margin-inline: auto;
+        margin-block: 5%;
+    }
+}
+.container-active {
+    background: black;
+}
diff --git a/src/main/resources/static/scripts/login.js b/src/main/resources/static/scripts/login.js
index 38ef327134aa8ae03ddc44ddf796b2df139fc3bb..df3b4ddf21b32933d0b283c60141be8e8eb5197c 100644
--- a/src/main/resources/static/scripts/login.js
+++ b/src/main/resources/static/scripts/login.js
@@ -1,51 +1,73 @@
-let username = document.forms["loginForm"]["username"];
-let password = document.forms["loginForm"]["password"];
-let pattern = new RegExp("^[a-z0-9_-]{3,15}$");
-
-username.addEventListener("input", validateUsername)
-password.addEventListener("input", validatePassword)
-
-function validateUsername() {
-    if (!(username.value === "") && pattern.test(username.value)){
-        username.classList.remove("invalid-field");
-        username.classList.add("valid-field");
-        document.getElementById(username.name+"Invalid").style.opacity = 0;
-        username.style.borderColor = "green";
-        return true;
-    } else if( ! (username.classList.contains("invalid-field") ) ){
-        username.classList.add("invalid-field");
-        username.classList.remove("valid-field");
-        document.getElementById(username.name+"Invalid").style.opacity = 1;
-        username.style.borderColor = "red";
+const container = document.getElementById('container');
+const registerBtn = document.getElementById('register');
+const loginBtn = document.getElementById('login');
+
+registerBtn.addEventListener('click', () => {
+    container.classList.add("active");
+});
+
+loginBtn.addEventListener('click', () => {
+    container.classList.remove("active");
+});
+
+
+const emailRegEx = new RegExp(/^[A-Za-z0-9.-_]+@[A-Za-z0-9.-]+\.[A-Za-z]+$/m);
+const passwordRegEx = new RegExp(/^[A-Za-z0-9_!#$%&'*+\/=?`{|}~^.-]+$/m);
+const usernameRegEx = new RegExp(/^[A-Za-z ]+$/m);
+
+function loginFormValidation(){
+    let pass= true;
+    let email = $("#login-email").val();
+    let password = $("#login-password").val();
+    if (email === "") {
+        alert("Email cannot be empty");
+        pass = false;
+    } else if ( !(emailRegEx.test(email)) ) {
+        pass = false;
+        alert("Invalid Email address")
     }
-    return false;
-}
-function validatePassword(){
-    if (password.value === "") {
-        password.classList.add("invalid-field");
-        password.classList.remove("valid-field");
-        document.getElementById(password.name+"Invalid").style.opacity = 1;
-        password.style.borderColor = "red";
-        return false;
-    } else if( ! (password.classList.contains("valid-field") ) ) {
-        password.classList.remove("invalid-field");
-        password.classList.add("valid-field");
-        document.getElementById(password.name+"Invalid").style.opacity = 0;
-        password.style.borderColor = "green";
+    if (password === "") {
+        alert("Password cannot be empty");
+        pass = false;
+    } else if ( !(passwordRegEx.test(password)) ) {
+        pass = false;
+        alert("Password contains invalid characters");
     }
-    return true;
+    return pass;
 }
 
-function validateForm(){
-    if (validateUsername() & validatePassword()) { //Using just & so it checks both, even if the first is false (it applies the style)
-        console.log("VALID");
-        return false;
-    } else {
-        console.log("Invalid");
-        document.getElementById("invalidLogin").style.opacity = 1;
-        return false;
+function registerFormValidation(){
+    /*WHYTF THIS DONT WORK*/
+    let pass=true;
+    let email = $("#register-email").val();
+    let username = $("#register-username").val();
+    let password = $("#register-password").val();
+
+    if (email == "") {
+        console.log("Email empty bit")
+        pass = false;
+        alert("Email cannot be empty");
+    } else if ( !(emailRegEx.test(email)) ) {
+        console.log("Email no match")
+        pass = false;
+        alert("Invalid Email address");
     }
-    //TODO SERVER SIDE VALIDATION AND CHECK AGAINST USERS DB TABLE
-}
 
+    if (username == "") {
+        pass = false;
+        alert("Username cannot be empty")
+    } else if ( !(usernameRegEx.test(username)) ) {
+        console.log(!usernameRegEx.test(username));
+        pass = false;
+        alert("Invalid username");
+    }
 
+    if (password == "") {
+        pass = false;
+        alert("Password cannot be empty");
+    } else if ( !(passwordRegEx.test(password)) ) {
+        pass = false;
+        alert("Password contains invalid characters");
+    }
+    return pass;
+}
\ No newline at end of file
diff --git a/src/main/resources/static/scripts/userPage.js b/src/main/resources/static/scripts/userPage.js
index 2c1d5069ad652b854abf6b8cb460d7ebf89d696f..a7b036197965493cbdd621b241350c56167bac08 100644
--- a/src/main/resources/static/scripts/userPage.js
+++ b/src/main/resources/static/scripts/userPage.js
@@ -1,6 +1,6 @@
-function updatePack(userid, packid) {
-    /* Updates the trail being shown on screen to the one requested by ID */
-    $.get("/packInfo/" + userid + "/" + packid).done(function (fragment) {
+function updatePack(url) {
+    /* Updates the trail being shown on screen */
+    $.get(url).done(function (fragment) {
         let packRewardsWrapper = $("#packRewardsWrapper");
 
         packRewardsWrapper.fadeTo("slow", 0, function () {
diff --git a/src/main/resources/static/sql/user-data.sql b/src/main/resources/static/sql/user-data.sql
new file mode 100644
index 0000000000000000000000000000000000000000..333ec4091f3ab1578e91009cca9fe9e3d9b7872d
--- /dev/null
+++ b/src/main/resources/static/sql/user-data.sql
@@ -0,0 +1,7 @@
+INSERT INTO users (username, password) VALUE ('Admin', 'admin');
+INSERT INTO users (username, password) VALUE ('Hannah', 'root');
+INSERT INTO users (username, password) VALUE ('Nigel', 'root');
+INSERT INTO users (username, password) VALUE ('Oscar', 'root');
+
+INSERT INTO authorities (username, authority) VALUE ('Admin', 'ADMIN');
+INSERT INTO authorities (username, authority) VALUE ('Hannah', 'USER');
diff --git a/src/main/resources/static/sql/user-progress-data.sql b/src/main/resources/static/sql/user-progress-data.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e9223384658ac8bd55456a60f9b8e52423b3d429
--- /dev/null
+++ b/src/main/resources/static/sql/user-progress-data.sql
@@ -0,0 +1,7 @@
+DELETE FROM stickerprogress;
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 1);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 2);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 3);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 5);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 2, 1);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 2, 3);
\ No newline at end of file
diff --git a/src/main/resources/templates/allTrails/allTrails.html b/src/main/resources/templates/allTrails/allTrails.html
index d29d1ad91cf459383b4681678742ed0a2cacbcd6..0fefa92c95a928454c100894149bf18340015baf 100644
--- a/src/main/resources/templates/allTrails/allTrails.html
+++ b/src/main/resources/templates/allTrails/allTrails.html
@@ -11,7 +11,7 @@
 <body>
 
 <header th:replace="~{/fragments/Templating.html :: header}"></header>
-
+<div>TEST</div>
 <main>
     <section id="allTrailsBar" class="centerFlex">
         <img class="trailsImages"
diff --git a/src/main/resources/templates/fragments/Templating.html b/src/main/resources/templates/fragments/Templating.html
index 55dba5e66042ad586fca111f9432a4c90f50742b..e3afc23854e38d5973a596f44e8d546305b59b83 100644
--- a/src/main/resources/templates/fragments/Templating.html
+++ b/src/main/resources/templates/fragments/Templating.html
@@ -9,15 +9,15 @@
             <li><a id="homeHead" href="/home">Home</a></li>
             <li>FAQs</li>
             <li>Contact us</li>
+            <li th:if="${#authentication.principal}!=anonymousUser"><a href="/logout">Log Out</a></li>
+            <li th:if="${#authentication.principal}==anonymousUser"><a href="/login">Log In</a></li>
         </ul>
-        <label class="work">Who  we Work with:</label>
-        <select>
-            <ul>
-                <option value="localauthorities">Local Authorities</option>
-                <option value="towns">Towns</option>
-                <option value="businesses"><a href="/businesses">Businesses</a></option>
-                <option value="consumers">Consumers</option>
-            </ul>
+        <label for="stakeholders" class="work">Who  we Work with:</label>
+        <select id="stakeholders">
+            <option value="localauthorities">Local Authorities</option>
+            <option value="towns">Towns</option>
+            <option value="businesses">Businesses</option>
+            <option value="consumers">Consumers</option>
         </select>
     </nav>
 </header>
diff --git a/src/main/resources/templates/users/login.html b/src/main/resources/templates/users/login.html
index 9c7aea8b67c0d18e2910b8c067ea576899fa6340..82f791b9acfff17bada66a547b3f2e3e7d79d29b 100644
--- a/src/main/resources/templates/users/login.html
+++ b/src/main/resources/templates/users/login.html
@@ -3,41 +3,71 @@
 <head>
     <meta charset="UTF-8">
     <title>User Log In</title>
-    <link rel="stylesheet" th:href="@{/css/userProfile.css}">
+    <link rel="stylesheet" th:href="@{/css/style.css}">
+    <link rel="stylesheet" th:href="@{/css/login.css}">
+    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
 
 </head>
 <body>
 
 <header>
-    <ul class="footerBar">
-        <li class="footerButton"><b>Home</b></li>
-        <li class="footerButton"><b>About</b></li>
-        <li class="footerButton"><b>Map</b></li>
-        <li class="footerButton"><b>Facilities</b></li>
-        <li class="footerButton"><b>Log In</b></li>
-    </ul>
+    <form name="logoutForm" th:action="@{/logout}" method="post" th:hidden="false">
+        <input hidden type="submit" value="Sign Out"/>
+        <button type="submit">CLICK ME OT LOG OUT</button>
+    </form>
 </header>
-<main  class="solidBg">
-    <div class="loginWrapper">
-        <form action="" onsubmit="return validateForm()" method="post" name="loginForm">
-            <h2>Log In</h2>
-            <div class="label">
-                <label for="username"><b>Username</b><br></label>
-                <div id="usernameInvalid" class="invalid-tooltip">Please fill out this field.</div>
-            </div>
-            <input type="text" name="username" id="username" placeholder="Enter Username" title="Username Input">
 
-            <div class="label">
-                <label for="password"><b>Password</b><br></label>
-                <div id="passwordInvalid" class="invalid-tooltip">Please fill out this field.</div>
+<main>
+    <!--CODE MODIFIED FROM: https://github.com/AsmrProg-YT/Modern-Login -->
+    <div class="container sign-in">
+        <div class="container" th:classappend="${status}" id="container">
+            <div class="form-container sign-up">
+                <form th:object="${user}" action="#" th:action="@{/login/register}" th:method="POST" onsubmit="return registerFormValidation()">
+                    <h1>Create Account</h1>
+                    <div th:if="${error.equals('User exists')}" class="alert alert-error">User already exist</div>
+                    <label>
+                        <input class="input" th:field="*{name}" id="register-username" type="text" placeholder="Name">
+                    </label>
+                    <label>
+                        <input class="input" th:field="*{email}" id="register-email" type="email" placeholder="Email">
+                    </label>
+                    <label>
+                        <input class="input" th:field="*{password}" id="register-password" type="password" placeholder="Password">
+                    </label>
+                    <button type="submit" >Sign Up</button>
+                </form>
             </div>
-            <input type="password" id="password" name="password">
-            <div id="invalidLogin">Username and/or Password incorrect. Please try again.</div>
-            <button type="submit"><b>Log In</b></button>
-        </form>
-
+            <div class="form-container sign-in">
+                <form  name="f" th:action="@{/login}" th:method="POST">
+                    <h1>Sign In</h1>
+                    <div th:if="${param.error}" class="alert alert-error">Invalid Username or Password</div>
+                    <label>
+                        <input class="input" id="username" type="text" name="username" placeholder="Email">
+                    </label>
+                    <label>
+                        <input class="input" id="password" type="password" name="password" placeholder="Password">
+                    </label>
+                    <a href="#" class="text">Forget Your Password?</a>
+                    <button type="submit">Sign In</button>
+                </form>
+            </div>
+            <div class="toggle-container">
+                <div class="toggle">
+                    <div class="toggle-panel toggle-left">
+                        <h1>Welcome Back!</h1>
+                        <p>Enter your personal details and start tracking your landmarks!</p>
+                        <button class="hidden" id="login">Sign In</button>
+                    </div>
+                    <div class="toggle-panel toggle-right">
+                        <div th:if="${param.logout}" class="alert alert-success">Successfully Logged out</div>
+                        <h1 th:if="!${param.logout}">Hello, Welcome!</h1>
+                        <p th:if="!${param.logout}">Register with your personal details and start earning stickers!</p>
+                        <button class="hidden" id="register">Sign Up</button>
+                    </div>
+                </div>
+            </div>
+        </div>
     </div>
-
 </main>
 
 
diff --git a/src/main/resources/templates/users/logout.html b/src/main/resources/templates/users/logout.html
new file mode 100644
index 0000000000000000000000000000000000000000..69107ce66e4b6c4b3ed49219e191e5335de6d9a2
--- /dev/null
+++ b/src/main/resources/templates/users/logout.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Logged Out Successfully</title>
+  <link rel="stylesheet" th:href="@{/css/style.css}">
+  <link rel="stylesheet" th:href="@{/css/login.css}">
+</head>
+<body>
+<main>
+  <div class="container centerAll">
+    <h1>You have successfully logged out</h1>
+  </div>
+</main>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/users/userProfile.html b/src/main/resources/templates/users/userProfile.html
index 3e865175760bc4b0aa11c9b54aade5d312ac55b5..edbe13918a53d466e7194ba42ff9dcf86bebdc56 100644
--- a/src/main/resources/templates/users/userProfile.html
+++ b/src/main/resources/templates/users/userProfile.html
@@ -3,6 +3,7 @@
 <head>
     <meta charset="UTF-8">
     <title th:text="'VZLA Profile Page of ' + ${user.getName()}"></title>
+    <link rel="stylesheet" th:href="@{/css/style.css}">
     <link rel="stylesheet" th:href="@{/css/userProfile2.css}">
     <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
 <!--    <link rel="stylesheet" th:href="@{/css/templatingstyle.css}">-->
@@ -38,7 +39,8 @@
                 <div th:each="pack : ${packs}"  class="packContainer">
                     <img class="packImg"   th:src="@{'../' + ${pack.getDisplayImg()}}"
                          th:id="'packImg' + ${pack.getId()}" th:alt="${pack.getName()}"
-                         th:onclick="'updatePack(' + ${user.getId()} +',' + ${pack.getId()} +');'">
+                         th:data-url="@{/packInfo/{username}/{packID}(username=${user.getName()}, packID=${pack.getId()})}"
+                         onclick="updatePack(this.getAttribute('data-url'))">
                     <h4 class="packName" th:text="${pack.getName()}"></h4>
                 </div>
             </div>
diff --git a/src/test/java/Team5/SmartTowns/DataSourceConfig.java b/src/test/java/Team5/SmartTowns/DataSourceConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb7623abb1831b13d72138f824b600d6ce361fa7
--- /dev/null
+++ b/src/test/java/Team5/SmartTowns/DataSourceConfig.java
@@ -0,0 +1,20 @@
+package Team5.SmartTowns;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+
+import javax.sql.DataSource;
+@Configuration
+public class DataSourceConfig {
+
+    @Bean
+    public DataSource dataSource(){
+        DriverManagerDataSource dataSource = new DriverManagerDataSource();
+        dataSource.setUrl("jdbc:mariadb://localhost:3306/test_towns");
+        dataSource.setUsername("root");
+        dataSource.setPassword("comsc");
+        return dataSource;
+    }
+
+}
diff --git a/src/test/java/Team5/SmartTowns/testUsers.java b/src/test/java/Team5/SmartTowns/testUsers.java
new file mode 100644
index 0000000000000000000000000000000000000000..2145c47165ed072b8a4c3478774da7410f881414
--- /dev/null
+++ b/src/test/java/Team5/SmartTowns/testUsers.java
@@ -0,0 +1,79 @@
+package Team5.SmartTowns;
+
+import Team5.SmartTowns.rewards.RewardsRepository;
+import Team5.SmartTowns.users.NewUser;
+import Team5.SmartTowns.users.User;
+import Team5.SmartTowns.users.UserRepository;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.*;
+
+@SpringBootTest
+public class testUsers {
+
+
+    @Autowired
+    UserRepository userRepository;
+    @Autowired
+    RewardsRepository rewardsRepository;
+
+    @Test
+    public void getAllUsersTest(){ // test if we can get all users, admin is sa known user
+        List<User> users = userRepository.getAllUsers();
+        User user = new User("Admin","Admin");
+        Assertions.assertEquals("Admin", users.get(0).getName());
+    }
+
+    @Test // test if new users can be added
+    public void addAUserTest(){
+        int userNumberBeforeAdd = userRepository.getAllUsers().size();
+        NewUser newuser = new NewUser("Meow","Woof","Cat@Dogs.com");
+        boolean trueIfAdded= userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword());
+        int userNumberAfterAdd = userRepository.getAllUsers().size();
+        assertTrue(trueIfAdded);
+    }
+
+    @Test // test if new users and inserted users can be found
+    public void doesUserExistTest(){
+        Boolean insertedUserFoundByEmail = userRepository.doesUserExist("Kevin@Gmail.com");
+        NewUser newuser = new NewUser("MeowMeow","WoofMeow","CatMeow@Dogs.com");
+        Boolean newUser = userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword());
+        Boolean newUserFoundByEmail = userRepository.doesUserExist(newuser.getEmail());
+        int compareTwoSearches = Boolean.compare(insertedUserFoundByEmail, newUserFoundByEmail);
+        assertEquals(0,compareTwoSearches); // if 0, both values are the same
+
+
+    }
+
+    @Test
+    public void canUsersUnlockStickersTest(){
+        NewUser newuser = new NewUser("MeowMeowMeow","WoofMeowMeow","CatMeowMeow@Dogs.com");
+        Boolean newUser = userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword());
+        Boolean doesStickerUnlock = userRepository.unlockSticker(newuser.getName(),2,2);
+        System.out.println(doesStickerUnlock);
+        assertTrue(doesStickerUnlock);
+    }
+    @Test
+    public void canUsersUnlockStickersAndViewThemTest(){
+        NewUser newuser = new NewUser("MeowMeowMeowMeow","WoofMeowMeowMeow","CatMeowMeowMeow@Dogs.com");
+        NewUser newuserTwo = new NewUser("Jumper","Baa","Sheep@Wool.com");
+        Boolean newUser = userRepository.addUser(newuser.getName(), newuser.getEmail(), newuser.getPassword());
+        Boolean newUserTwo = userRepository.addUser(newuserTwo.getName(), newuserTwo.getEmail(), newuserTwo.getPassword());
+        Boolean doesStickerUnlock = userRepository.unlockSticker(newuser.getName(),1,2);
+        List<Long>  newUserStickerCollection = userRepository.getUserStickersFromPack(newuser.getName(),1);
+        List<Long>  newUserStickerCollectionTwo = userRepository.getUserStickersFromPack(newuserTwo.getName(),1); // compare and see if only new suer that has unlocked a sticker ahs one in their collection for pack 1
+        int newUserStickerList = newUserStickerCollection.size();
+        int newUserStickerListTwo = newUserStickerCollectionTwo.size(); // should have different sizes
+        assertNotSame(newUserStickerList,newUserStickerListTwo);
+
+    }
+
+
+}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..83f47c5db5a7390e1ab3dadf4882c3ddf1e3b4ea
--- /dev/null
+++ b/src/test/resources/application.properties
@@ -0,0 +1,8 @@
+spring.datasource.url=jdbc:mariadb://localhost:3306/
+spring.datasource.username=root
+spring.datasource.password=comsc
+
+spring.sql.init.mode=always
+spring.sql.init.platform=test
+spring.sql.init.schema-locations=classpath:schema-test.sql
+spring.sql.init.data-locations=classpath:test-data.sql
\ No newline at end of file
diff --git a/src/test/resources/schema-test.sql b/src/test/resources/schema-test.sql
new file mode 100644
index 0000000000000000000000000000000000000000..744c10245fa965d81b641fc0cf3231ea612782a7
--- /dev/null
+++ b/src/test/resources/schema-test.sql
@@ -0,0 +1,110 @@
+
+
+
+
+DROP DATABASE IF EXISTS test_towns;
+CREATE DATABASE IF NOT EXISTS test_towns;
+USE test_towns;
+DROP TABLE IF EXISTS trails;
+DROP TABLE IF EXISTS locations;
+DROP TABLE IF EXISTS users;
+DROP TABLE IF EXISTS stickers;
+DROP TABLE IF EXISTS packs;
+DROP TABLE IF EXISTS stickerProgress;
+
+
+CREATE TABLE IF NOT EXISTS trails (
+                                      trailID bigint auto_increment primary key,
+                                      name varchar(128),
+                                      tru boolean
+)   engine=InnoDB;
+
+drop table if exists locationCoordinates;
+drop table if exists locations;
+create table if not exists locations
+(
+    locationID bigint auto_increment primary key,
+    locationName varchar(128),
+    locationEmail varchar(128),
+    locationDescription longtext,
+    locationPlace varchar(255),
+    locationTrailID varchar(128),
+    locationApproved boolean
+)   engine=InnoDB;
+CREATE TABLE IF NOT EXISTS users (
+                                     username varchar(30) primary key NOT NULL,
+                                     id bigint auto_increment unique, /*DEPRECATED COLUMN, LEFT IN WHILE SOME OTHER FUNCTIONS STILL USE IT*/
+                                     email varchar(128),
+                                     password varchar(30) NOT NULL,
+                                     enabled boolean default true
+);
+
+CREATE TABLE IF NOT EXISTS authorities (
+                                           id bigint primary key auto_increment NOT NULL,
+                                           username varchar(30) NOT NULL ,
+                                           authority varchar(45) NOT NULL
+);
+
+CREATE TABLE IF NOT EXISTS packs (
+                                     id bigint auto_increment primary key,
+                                     name varchar(20) NOT NULL,
+                                     description text
+);
+
+CREATE TABLE IF NOT EXISTS stickers (
+                                        id bigint auto_increment primary key,
+                                        packID bigint NOT NULL,
+                                        FOREIGN KEY (packID) REFERENCES packs(id)
+                                            ON DELETE CASCADE
+                                            ON UPDATE RESTRICT,
+                                        stickerID bigint NOT NULL, /*STICKER ID NUMBER WITHIN ITS OWN PACK*/
+                                        name varchar(30) NOT NULL,
+                                        description text NOT NULL,
+                                        rarity tinyint
+);
+
+CREATE TABLE IF NOT EXISTS stickerProgress (
+                                               id bigint auto_increment primary key,
+                                               username varchar(30) NOT NULL,
+                                               FOREIGN KEY (username) REFERENCES users(username)
+                                                   ON DELETE CASCADE
+                                                   ON UPDATE RESTRICT,
+                                               packID bigint NOT NULL,
+                                               FOREIGN KEY (packID) REFERENCES packs(id)
+                                                   ON DELETE CASCADE
+                                                   ON UPDATE RESTRICT,
+                                               stickerID bigint NOT NULL,
+                                               FOREIGN KEY (stickerID) REFERENCES stickers(id)
+                                                   ON DELETE CASCADE
+                                                   ON UPDATE RESTRICT
+);
+
+create table if not exists locationCoordinates
+(
+    locationCoordID bigint auto_increment primary key,
+    locationID bigint,
+    Foreign Key (locationID) REFERENCES locations(locationID)
+        ON DELETE CASCADE
+        ON UPDATE RESTRICT,
+    locationCoordsLat DECIMAL(8,6),
+    locationCoordsLong DECIMAL(8,6)
+
+
+)engine=InnoDB;
+
+
+drop table if exists townsWithTrails;
+create table if not exists townsWithTrails
+(
+    townID bigint auto_increment primary key,
+    townName varchar(128),
+    townCentreCoordsLat varchar(128),
+    townCentreCoordsLong varchar(128),
+    townUppermostCoordsLat varchar(128),
+    townLowermostCoordsLat varchar(128),
+    townLeftmostCoordsLong varchar(128),
+    townRightmostCoordsLong varchar(128)
+
+)engine=InnoDB;
+
+
diff --git a/src/test/resources/test-data.sql b/src/test/resources/test-data.sql
new file mode 100644
index 0000000000000000000000000000000000000000..05db12e66b276dace05661710dff01ba513875d7
--- /dev/null
+++ b/src/test/resources/test-data.sql
@@ -0,0 +1,68 @@
+delete from trails;
+insert into trails ( Name,tru) value ( 'Caerphilly Coffee Trail',false);
+insert into trails ( Name,tru) value ( 'Penarth Dragon Trail',true);
+
+delete from locations;
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'St Cenydd','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Castle','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Medieval Trades','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Queen''s War','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Green Lady','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Armoury','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Architecture','','Location description here','Caerphilly',0101, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( '21st Century Landmark','','Location description here','Caerphilly',0101, true);
+
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'JD Wetherspoons-Malcolm Uphill','','Location description here','Caerphilly',0102, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Cwtch','','Location description here','Caerphilly',0102, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Conservative Club','','Location description here','Caerphilly',0102, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The King''s Arms','','Location description here','Caerphilly',0102, true);
+
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Caerphilly Bus Station','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Medieval Courthouse','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ('Caerphilly Castle','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Ty Vaughan House','','Location description here','Caerphilly',0103, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Risca Colliery','','Location description here','Risca',0201, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'Black Vein Colliery Disaster','','Location description here','Risca',0201, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Esplanade','','Location description here','Penarth',0301, true);
+insert into locations ( locationName , locationEmail,locationDescription,locationPlace, locationTrailID, locationApproved) value ( 'The Old Swimming Baths','','Location description here','Penarth',0301, true);
+
+
+
+
+
+DELETE FROM packs;
+INSERT INTO packs (name, description) VALUE ('Wales Football Team', 'Pack of Welsh Football Players in the National Team');
+INSERT INTO packs (name, description) VALUE ('Wales Rugby Team', 'Pack of Welsh Rugby Players in the National Team');
+INSERT INTO packs (name, description) VALUE ('Welsh Heritage', 'Pack About Welsh Heritage');
+
+DELETE FROM stickers;
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 1, 'wayne_hennessey', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 2, 'neco_williams', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 3, 'joe_morrell', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 4, 'ethan_ampadu', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (1, 5, 'connor_roberts', 'Wales Football Team Player', '2');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 1, 'Taine_Basham', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 2, 'Adam Beard', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 3, 'Elliot Dee', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 4, 'Corey Domachowski', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (2, 5, 'Ryan Elias', 'Wales Rugby Team Player', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 1, 'Welsh Lady', 'Welsh Heritage', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 2, 'Welsh Outline', 'Welsh Heritage', '1');
+INSERT INTO stickers (packID, stickerID, name, description, rarity) VALUE (3, 3, 'Welsh Spoon', 'Welsh Heritage', '1');
+
+INSERT INTO users (username, password) VALUE ('Admin', 'admin');
+INSERT INTO users (username, password) VALUE ('Hannah', 'root');
+INSERT INTO users (username, password) VALUE ('Nigel', 'root');
+INSERT INTO users (username, password) VALUE ('Oscar', 'root');
+INSERT INTO users (username, email, password) VALUE ('kevin','Kevin@Gmail.com' ,'root');
+
+INSERT INTO authorities (username, authority) VALUE ('Admin', 'ADMIN');
+INSERT INTO authorities (username, authority) VALUE ('Hannah', 'USER');
+
+DELETE FROM stickerprogress;
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 1);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 2);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 3);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 1, 5);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 2, 1);
+INSERT INTO stickerprogress (username, packID, stickerID) VALUE ('Admin', 2, 3);