How to Write, Schedule and Publish Your First Post
From an empty composer to a live post: what each button does, how scheduling timezones work, what the queue and calendar are for, and what happens when only some platforms accept the post.
FIRST POST
Once an account is connected, everything else happens in three places: the composer, where you write; the calendar, where you see and change what is coming; and the queue, where the same posts are listed as a flat, filterable timeline. They are three views of one list, not three separate systems, which means a post you create in one shows up in the others immediately.
This guide walks through the whole path in order, and it is deliberately explicit about three things that confuse people on day one: what the Post now button really does, which timezone the scheduler is using, and why a post can end up published on four platforms and failed on a fifth.
Before you write: the composer's inputs
Open Compose from the sidebar. The editor is a single card with five inputs, and each one has a rule attached.
The text box. Your post needs at least five characters. Under the header you will see a counter that reads something like 214 left · X / Twitter limit. That second half matters: the composer caps the global text at the tightest limit among the platforms you have selected. Select only LinkedIn and you can write three thousand characters. Add X to the selection and the counter drops to 280, because if the post is going to X as well, it has to fit there too.
This is not a bug and it is not a random number. It is the difference between writing once for a set of accounts and writing once for the strictest account in that set. When you want a longer version somewhere else, you use the per-platform override further down the page rather than removing platforms from the selection.
The platform picker. Only connected accounts appear, and only the ones you have actually authorised. If the section shows an empty state with a Connect an account button, that is your signal to go back to the accounts page — the composer will not let you target a network you have not connected. When you open the picker with accounts available, the first two are selected by default, which is a convenience rather than a rule; change it to whatever the post is for.
The image. One image per post, PNG, JPG, WEBP or GIF, up to 10 MB, uploaded to the server before the post row is created. Two platform-specific rules are enforced while you pick the file rather than after you press publish: if Dribbble is among your selected platforms, the image must be exactly 400x300 or 800x600 pixels, because Dribbble rejects every other size; and the file must really be an image, since the upload endpoint accepts image MIME types only.
The plan card. If your plan has a post allowance, the composer shows how many posts remain. If X is selected, a small amber chip shows the estimated cost of this post — 0.015 dollars without a link, 0.200 dollars if the text contains a URL. X is the only platform in the product that charges per post, and the chip is there so the number is visible before you commit rather than on an invoice later.
The per-platform override. Untick nothing, change everything. Each selected platform gets its own tab where you can write a different version of the text — a longer LinkedIn version, a hashtag-heavy Instagram version, a shorter X version. If you leave a platform's override empty, the global text is used for it. The button under a filled override reads Use global text instead, which clears just that platform.
Three buttons, three different meanings
At the bottom of the composer there are three actions, and they are genuinely different, not three flavours of the same save.
Save draft
Creates the post with draft status and sends you to the calendar. A draft has no time attached and will never be picked up by the scheduler. It is the right choice when the idea is right but the wording is not, and it is also the right choice when you want to build a week of posts on Monday and approve them later.
Schedule post
Requires a date and time, and this is where the timezone question gets answered. The value you type in the date-time field is your computer's local clock. PostHub converts it to UTC the moment it reaches the server, stores it that way, and the scheduler compares it against UTC. In other words: the time you pick is the time it goes out, in the timezone you are sitting in. If you are in Karachi and you schedule for 9:00 PM, the post goes out at 9:00 PM Karachi time, not 9:00 PM UTC.
The scheduled post appears in the calendar and in the queue immediately, with status scheduled, and nothing else happens until its moment arrives.
Post now
This one publishes. Not "marks as published" — actually pushes the post to every selected platform through the publishing engine, in the same request. You get a success toast naming the outcome, and you are taken to the calendar.
If every platform accepts, the toast says the post is live on every selected platform. If some of them reject it, you get a warning that tells you how many platforms failed, because the ones that succeeded really did succeed and rolling your eyes at the whole post would be wrong. If all of them reject it, the request comes back as an error, the post is saved with failed status, and the message names the first reason.
That last point is worth internalising: Post now is synchronous. It waits for the platforms to answer. If you have selected four networks, you are waiting for four responses, and a slow one holds the button. That is deliberate — it would be worse to show you a green tick and find out later that nothing went out.
What the calendar is for
The calendar is the visual view of everything you have created: drafts on their creation day, scheduled posts on the day they will go out, published posts on the day they went out.
Three views sit at the top: month, week and list. Month is for glancing, week is for spotting gaps, list is for reading. Each view groups posts by day, and the day label is computed in your timezone, so a post scheduled for just past midnight appears on the day you meant, not the UTC day it was stored under.
Clicking any post opens a detail modal with the full text, the platforms it targets and, when there is one, the image. From that modal you can do four things.
Edit the text. Only drafts and scheduled posts can be edited; a post that has already gone out is immutable, because editing a published post would not change what the platforms received.
Change the time. The date-time field in the modal is pre-filled with your local time for that post. Change it, save, and the new UTC value is stored. The scheduler notices on its next pass.
Drag it to another day. In month and week view you can grab a post and drop it on a different day. The time of day is preserved and only the date moves. A confirmation toast names the new day.
Publish now. The modal has an explicit publish action that posts immediately through the same engine as the composer's Post now. This is the correct tool for a post you scheduled for tomorrow and just found out needs to go out today.
After a post has been published, the modal switches from edit controls to a read-only view with its status, because there is nothing left to change.
What the queue is for
The queue is the same data without the grid: a flat list, grouped by day, with filter chips across the top for all, scheduled, draft, published and failed, plus a dropdown to narrow by platform.
Use the queue when you are checking rather than planning. The three questions it answers fast are: what goes out today, what is still a draft, and what failed. The failed filter is the one to remember, because a post that failed on one platform still shows as published overall — the queue's failed chip is where the platform-level failure lives, and opening the post from there shows you the reason.
The queue does not edit. That is not an oversight; editing happens in the calendar modal so that there is exactly one place where a post's text and time can change.
The scheduler: what happens when a time arrives
Behind the scenes the server wakes up once a minute, asks which scheduled posts are now due, and publishes them in order of how overdue they are, up to ten at a time.
For each due post it resolves the image once and hands the same file to every platform adapter, then records the outcome per platform: the id the platform assigned, the URL of the published post where the platform returns one, and the error if it refused. On success the post becomes published and gets a published-at timestamp; on total failure it becomes failed with the reasons stored against it; on a partial result it is marked published, with the rejected platforms recorded alongside.
Three consequences follow from that design, and all three are useful to know before they surprise you.
A scheduled post needs its time to be in the future. Schedule something for two minutes from now and it will go out on the next pass; schedule something that has already passed and you are relying on the next tick catching it, which it will, but you have given up control of the exact second.
Ten at a time is a deliberate ceiling. If you schedule twenty posts for the same minute — which happens when someone bulk-loads a week and gets the timezone wrong — the first ten go out now and the rest go on the next pass. Nothing is dropped, but the order is by scheduled time, so the earliest posts win.
A failure does not retry itself. If a platform is down or a token has expired, the post is marked failed and stays failed. Open it, fix the cause, and publish again from the calendar modal. Silent retries would hide the problem and could double-post if the first attempt had actually landed.
The timezone rule, stated once
Everything about time in this product follows one rule: you pick local, the database stores UTC, the scheduler compares UTC.
The date-time input in the composer and the calendar modal reads your browser's clock. That value is converted to an ISO timestamp in UTC before it is stored. When you look at the calendar, the queue or the dashboard's next-scheduled card, the value is converted back into your local timezone for display. So the number you see is always the number you meant.
The places where this goes wrong are the places where a timezone is not carried through: importing a spreadsheet of times with no offsets, or comparing a wall-clock string from another system against UTC. If you ever see a post that went out five or eight hours early, the first question to ask is whether the source of that time knew its timezone.
Day grouping follows the same rule. Posts are bucketed under the calendar day you are in, so a post scheduled for 1:00 AM on Saturday appears on Saturday even though it is Friday evening in UTC.
Publishing to a platform that only accepts video
The composer attaches an image. That is a real constraint, not a placeholder: the file picker accepts images, the upload endpoint accepts images, and the preview renders an image.
YouTube, TikTok and Vimeo accept video only. If you select one of those in the composer and press publish, the platform will refuse the post because there is no video attached, and you will see a media-related error naming that platform. The other platforms in the same selection will still have received the post, so the result will be partial rather than a total failure.
The practical rule until video uploads land: select video platforms from the calendar's publish action only when you have a post that was created with a video attached, and treat the composer as the image-and-text path. If you only need to publish to video platforms, keep them out of the composer selection so that a post does not go out half-successfully and leave you to reason about which half worked.
Statuses, and how to read them
Four statuses appear across the app, and each one has a precise meaning.
Draft means saved, not scheduled, not published. It will not go out on its own. Drafts are where unfinished work lives.
Scheduled means it has a time and the scheduler owns it. Until that time arrives, you can edit it, move it, or open it and publish it early.
Published means the engine finished and at least one platform accepted. Check the post detail for the per-platform result when you need to know which ones.
Failed means nothing accepted it. The post still exists — nothing is deleted on failure — and the reason is stored with it.
There is one subtlety worth calling out because it surprises people: a post that succeeded on three platforms and failed on one is shown as published, not partial. The system records which platforms rejected it, but the post's headline status reflects the fact that it went out. When you see a published post with an odd feeling about it, open it and read the per-platform lines rather than trusting the badge alone.
A worked example: the first ten minutes
If you want to follow along rather than read, this is the shortest useful path through the product.
Connect one OAuth account and Bluesky, so you have exercised both connection styles. Open the composer, select both, and watch the counter settle on the tighter of the two limits — 280, because X is in the selection.
Write something short. Add an image if you have one. Press Save draft and confirm it appears in the calendar.
Open it in the calendar, change the status by pressing Schedule post with a time three minutes from now, and watch the queue show it under the right day.
When the minute passes, refresh the queue. The post reads published, and opening it shows a per-platform result for each network you targeted.
Now repeat with Post now and note that the response is immediate and the toast tells you the number of platforms that rejected it, if any. That difference — scheduled work happens on a timer, immediate work happens in your request — is the entire model.
Common first-week mistakes
Scheduling into the past by accident. Pick a date before today and the scheduler will treat it as overdue. Nothing breaks, but you lose control of the timing.
Leaving the composer with unsaved text. There is no autosave. If you navigate away mid-sentence, the text is gone. Save a draft if you need to leave.
Selecting every connected platform by default. The first two accounts are selected for you. That is a starting point, not a recommendation — a post that belongs on LinkedIn rarely belongs on Bluesky in the same words, and the per-platform override exists precisely so you can stop pretending it does.
Ignoring a failed post. Failed posts stay in the queue under the failed filter forever until you act. They are not retried and they do not disappear.
Expecting video. The composer is images and text. Video platforms will refuse an image-only post, and that refusal is correct behaviour from their side.
Retrying a partial publish (and why it is safe)
A partial result means some platforms accepted the post and others refused it. The post is marked published, the successful platforms have their own post ids stored against them, and the failed platforms have nothing stored.
When you fix the cause — reconnect an expired account, shorten a caption that was over a limit, replace an image that was the wrong size — you can press publish again from the calendar modal. On this pass the engine looks at each targeted platform row and skips any that already has a platform post id. It does not re-send to the networks that worked.
That skip is the entire reason retries are safe. Without it, fixing a one-platform failure would mean a second copy of the post appearing on the three networks that were fine the first time, which is the kind of mistake that is very visible to your audience and impossible to undo. With it, a retry only ever touches the platforms that have not received anything yet.
The same rule makes a double press of the publish button harmless. Two clicks in quick succession produce two requests; the second one finds every row already has an id and simply reports success for the platforms that are done.
What retrying does not do is diagnose the problem for you. The error text stored against the failed platform is the same message you saw the first time, and it is the thing worth reading before you press anything — because if the failure was a content rule rather than a connection problem, the retry will fail in exactly the same way and you will have learned nothing except that the post is still not fully out.
Approvals: a second pair of eyes before anything goes out
If more than one person touches the content, there is a separate path: Approvals in the sidebar.
Approvals lists posts that are waiting for a decision alongside the connected accounts they would go to. From that screen, Approve is a real action — it publishes the post immediately through the same engine as everything else in this guide, and it does so as the person pressing the button. Reject and Request changes record your decision and move the post out of the way without publishing anything.
Two properties of this screen matter before you build a workflow on it.
First, it is a one-way gate rather than a full review cycle. Rejecting a post does not send it back to its author with your comment attached; it marks the decision locally in your browser so that your view of the queue is clean. If you need the author to actually see feedback, that conversation still happens wherever your team already talks to each other.
Second, the "assigned to" line on each card is informational. There is no invitation system in this build, no per-seat roles and no email that goes out when something lands in Approvals. Everyone who can see the account can approve.
Used honestly, the screen does one thing very well: it keeps publishing behind a deliberate human action. A post that is drafted by someone who should not be able to publish directly sits in Approvals until someone with the authority presses Approve, and that single press is what moves it from a draft to a live post on real networks. For a small team that is the difference between "nobody can post by accident" and "anyone with the login can post".
If you are working alone, you do not need it — the composer's Schedule post button already gives you the pause between writing and publishing, and a scheduled post can sit for a day, a week or a month before the timer takes over.
What the dashboard tells you about your schedule
The dashboard's top cards are derived from the same post list, and they answer the questions you would otherwise open three pages to answer.
The next scheduled card shows the single soonest scheduled post with its weekday and time in your local timezone, or reads Nothing queued when nothing has a time attached. It is the fastest confirmation that the thing you just scheduled really is in the system — if you pressed Schedule post and this card is empty, the post did not save.
Nearby cards summarise how many posts are in each state, so a glance tells you whether you have a healthy forward queue or a pile of drafts nobody has scheduled. The recent-posts list under them shows the last few items with their status and, for scheduled ones, the time.
Everything on that page is a view of real rows. Nothing is a sample, and nothing there is a forecast — if the dashboard says three posts are scheduled, three posts are scheduled.
Writing one draft for five networks without sounding like a bot
The composer lets you select five platforms and type once. It also lets you override the text per platform. Knowing when to use which is the difference between a schedule that reads like a person and one that reads like a syndication feed.
Use the global text when the post is genuinely the same everywhere: a service notice, a launch time, a link that has to say the same thing. Use the overrides when the platforms have different expectations — X wants 280 characters and no preamble, LinkedIn wants a paragraph of context before the point, Instagram wants a hook in the first line because the rest is hidden behind a caption fold, Threads sits between the two.
A practical pattern that works for most teams: write the global version as the shortest complete thought — the version that would still make sense if it were the only line someone read. Then write the LinkedIn override as the same idea with the reasoning attached, and the Instagram override as the same idea with the hashtags moved to the end. Three edits, not three posts, and nothing sounds copy-pasted.
The counter helps here rather than fighting you. Because the global counter reflects the tightest selected platform, it keeps the shared version honest. The per-platform counter on each override tab is where you find out how much room LinkedIn or Facebook actually gave you.
What to avoid is the other direction: selecting every platform because it is ticked, writing once, and publishing identical text to five networks at the same minute. It is not against any rule in the product, and audiences notice it anyway. If a platform genuinely has nothing to add to a given post, removing it from the selection is a better decision than forcing it in.
Choosing times without overthinking it
Most of the agonising over posting times is not worth the hour it consumes, because a scheduling tool's real job is reliability rather than clairvoyance. Three rules cover almost every situation.
Be consistent before you are clever. Publishing at the same three or four slots each week is worth more than publishing at the mathematically optimal minute, because consistency is what a returning audience can actually plan around. Pick slots, put them in the calendar, and keep them for a month before changing anything.
Do not schedule five posts for the same minute. Cross-posting one idea to four platforms at the identical timestamp is technically fine and looks automated everywhere. Stagger them by a few minutes — which in practice means scheduling the platform variants slightly apart — or accept that the simultaneity is visible.
Match the slot to the platform's rhythm, not to a global average. Professional audiences on LinkedIn and X are weekday creatures; Instagram and TikTok tolerate evenings and weekends; a blog-announcement post on any network does better in working hours than at 2 am. You already know your audience's rough shape, and guessing from that beats reading somebody else's study of a different niche.
What is worth tracking, once you have a few weeks of history: which day of the week produced your best week, and whether a post that went out at the wrong hour still performed. The analytics screen's posts-per-week chart answers the first; the platform's own analytics answers the second.
What is not worth tracking: minute-by-minute heat maps imported from a generic report. The variance they promise is smaller than the variance introduced by one inconsistent week, and the confidence they create is not earned.
The overriding rule, though, is the one this guide keeps returning to: a post at a good time that actually goes out beats a post at a perfect time that you forgot to schedule.
Editing a scheduled post before it goes out
Everything about a scheduled post can be changed until the moment the scheduler picks it up, and knowing which parts are safe to change removes the hesitation people feel around editing.
Text and media: change freely. The post is read from the database when the publish runs, not snapshotted when it was scheduled, so an edit made an hour before — or a minute before — is what goes out.
Platforms: change freely, with one consequence to understand. If you remove a platform that has already received the post through an earlier publish, removing it does not retract what was published; it only prevents a future publish from touching it. Retraction is a platform-side action, done in that platform's own interface.
Time: change freely, in either direction. Moving a post later is the normal correction. Moving it earlier only matters if the new time has already passed, in which case the scheduler treats it as due on its next pass — within a minute or so — so a post you meant to move forward a day can go out almost immediately if you are careless with the date.
Status: a scheduled post can be returned to draft, which stops the timer entirely. This is the correct action when you are unsure, because it is reversible in a way that an accidental publish is not.
The one thing to re-check after any edit is the time. Changing text invites a quick save; changing text and time invites a save where the time field was left in a state you did not intend. Glance at the queue once afterwards and confirm the day and hour still read the way you expect.
What scheduling is not
It is worth stating the boundaries, because a scheduling tool invites a couple of expectations it cannot meet.
Scheduling is not distribution intelligence. Choosing 9:14 on a Wednesday because a chart told you to is not the same as knowing your audience, and a tool that accepts any time you type will happily accept a bad one with the same confidence as a good one.
Scheduling is not a substitute for showing up afterwards. The post goes out whether or not you are there to answer the comment that follows, and the value of a comment arriving while you are asleep is close to zero. Plan the twenty minutes after a post lands with the same seriousness as the post itself.
Scheduling is not publishing on your behalf in the legal sense either. The content is yours, the account is yours, and the platform's rules apply to what it sends exactly as they would to anything you posted by hand.
And scheduling is not permanent commitment. Every scheduled post can be edited, delayed or returned to draft right up until the moment the scheduler picks it up. The queue exists so that you can see the future state of your publishing and change it — which is the difference between a schedule and a promise.
Where to go next
The queue and calendar will carry you a long way on their own. When you are ready to go deeper, the next useful topics are media requirements, which explains exactly why a specific platform rejected your image, and the failed-publish guide, which turns each error message into a concrete fix.
Before you close this page, one habit is worth building: after you schedule anything, glance at the queue filter for today. It takes two seconds and it is the only place where you will notice a post that did not go out the way you expected.
Put this playbook on autopilot
PostHub queues, publishes and reports across every platform you use — so the strategy above actually happens without you babysitting a tab.