Touched events for client and server

I wanna do checks for objects being touched on both the client and server (so I can do different stuff based on where the codes running) and I don’t want to rely on RemoteEvents due to delays. Currently I have 2 modules, 1 being required from server, other from client, look like so

-- Server
local Checkpoints = {}

local Players = game:GetService('Players')

local Tower = workspace:WaitForChild('Tower')

local TouchDebounce = {}

local TouchConnection

-- Disconnect events
function Checkpoints.Disconnect()
	if not TouchConnection then return end
	
	TouchConnection:Disconnect()
end

-- Setup checkpoints
function Checkpoints.Setup()
	for _, v in pairs(Tower:GetChildren()) do
		local Checkpoint = v:FindFirstChild('Checkpoint')
		if Checkpoint then
			TouchConnection = Checkpoint.Touched:Connect(function(hit)
				local Character = hit.Parent
				if not Character then return end
				
				local Player = Players:GetPlayerFromCharacter(Character)
				if not Player then return end
				
				if table.find(TouchDebounce, Player) then return end
				
				table.insert(TouchDebounce, Player)
				
				wait(1)
				
				local PlayerIndex = table.find(TouchDebounce, Player)
				if PlayerIndex then
					table.remove(TouchDebounce, PlayerIndex)
				end
			end)
		end
	end
end

return Checkpoints
-- Client
local Checkpoints = {}

local Players = game:GetService('Players')
local TweenService = game:GetService('TweenService')

local Tower = workspace:WaitForChild('Tower')

local TouchConnection

for _, v in pairs(Tower:GetChildren()) do
	local Checkpoint = v:FindFirstChild('Checkpoint')
	if Checkpoint then
		TouchConnection = Checkpoint.Touched:Connect(function(hit)
			local Character = hit.Parent
			if not Character then return end
			
			local Player = Players:GetPlayerFromCharacter(Character)
			if not Player then return end
			
			if hit.Name ~= 'Right Leg' and hit.Name ~= 'Left Leg' then return end
			
			local SizeTween = TweenService:Create(Checkpoint, TweenInfo.new(), {Size = Vector3.new(0, 0.05, 0)})
			SizeTween:Play()
			SizeTween.Completed:Wait()
			
			Checkpoint:Destroy()
			TouchConnection:Disconnect()
		end)
	end
end

return Checkpoints

Is there something I could be doing to put this under 1 module?

I am not pretty sure if this is going to work out for your case, but just saying you can use RunService:IsServer function to check if its the server / client. After you have got that part, you can keep the module in RS and require from both server & client. Then for the functions you just check if its Server, or not.