In fact, you don’t need to do this on the client. Use your script to see what the movement on the server looks like. You will see that everything is out of sync. Why do you need to set a new board position every frame if Weld does it for you?
Server script:
local RunService = game:GetService("RunService")
local Players = game.Players
game.Players.PlayerAdded:Connect(function(player)
local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:WaitForChild("HumanoidRootPart")
local boards = game:GetService("ReplicatedStorage").Boards
local PlayerBoard = --[[here u can create async with datastore]] boards.SimpleBoard:Clone()
PlayerBoard.Parent = workspace
PlayerBoard.Position = hrp.Position + Vector3.new(0, -3.15, 0)
local weld = Instance.new("WeldConstraint")
weld.Part0 = hrp
weld.Part1 = PlayerBoard
weld.Parent = PlayerBoard
end)
If you will try to do this on the client (which is the best solution) then you should implement a system for predicting the player’s position in order to properly synchronize the desks with the player on the server.