diff --git a/site/content/blog/release-0.30.0.md b/site/content/blog/release-0.30.0.md
new file mode 100644
index 0000000..c6c2d69
--- /dev/null
+++ b/site/content/blog/release-0.30.0.md
@@ -0,0 +1,219 @@
+---
+title: "Release 0.30.0 is out!"
+date: 2023-02-21T20:00:00-07:00
+draft: false
+---
+
+`rust-bitcoin` version 0.30.0 is out now.
+
+
+
+This is a rather large release so we decided to write an update guide for you guys. If this guide is
+not useful or lacking in some way please do let us know so we can do better.
+
+First a little excuse for why this is going to be so painful. We try to deprecate things when we
+make API breaking changes, using
+
+ #[deprecated(since = "x.y.z", note = "use foobar instead")]
+
+This allows us to give you a hint on how to upgrade by way of the compiler. The problem we hit was
+that its not always possible to deprecate things (e.g. changing arguments to a function) so under
+the cover of "this is a pre-1.0 release" and with the aim of pushing kind of fast so we can get to
+the 1.0 release, we got a bit sloppy with deprecation this release - sorry about that. We are very
+much trying to get to a place where we can commit to our APIs and stabilize the codebase, that is
+the primary goal of development at the moment. If you have API changing suggestions or requests
+please get them into us now so your needs can be met.
+
+Without further ado, here is the upgrade guide. Enjoy!
+
+## Suggested steps
+
+We suggest that you take these steps when upgrading:
+
+0. Make sure to update other dependency versions in `Cargo.toml` if you use them explicitly: `bitcoin_hashes` to 0.12.0, `secp256k1` to 0.27.0
+1. Remove all occurrences of `util::` referring to our crate
+2. Replace `Script` with [`ScriptBuf`](https://docs.rs/bitcoin/0.30.0/bitcoin/script/struct.ScriptBuf.html) (`s/\([^A-Za-z0-9]\)Script\([^A-Za-z0-9]\)/\1ScriptBuf\2/g` should work in most cases)
+3. Replace instances of `.parse::
()` with `.parse::>()`
+4. Call `require_network(network)` on parsed addresses (you'll get no method found for `Address` errors)
+5. Replace `locktime` with [`locktime::absolute`](https://docs.rs/bitcoin/0.30.0/bitcoin/locktime/absolute/index.html)
+6. Replace `PackedLockTime` with just [`LockTime`](https://docs.rs/bitcoin/0.30.0/bitcoin/locktime/absolute/struct.LockTime.html)
+7. Import key types from the `key` submodule rather than `schnorr` or `ecdsa`
+8. Replace `SchnorrSighashType` with [`TapSighashType`](https://docs.rs/bitcoin/0.30.0/bitcoin/sighash/struct.TapSighashType.html)
+9. Replace `TapBranchHash` with [`TapNodeHash`](https://docs.rs/bitcoin/0.30.0/bitcoin/taproot/struct.TapNodeHash.html)
+10. Change `hash_newtype!(FooHash, sha256::Hash, 32, doc="A hash of foo.");` to:
+
+```rust
+hash_newtype! {
+ /// A hash of foo.
+ pub struct FooHash(sha256::Hash);
+}
+```
+
+11. Fix outstanding compiler errors, if any
+12. Optimize the code: replace occurrences of `&ScriptBuf` with `Script`, remove allocations...
+13. Remove useless conversions `LockTime` -> `LockTime` (clippy has a lint for it)
+
+These steps should get you most of the way - see "Renames" section below also.
+
+## Re-exports
+
+We are trying to separate the API from the directory structure, as part of this we are attempting to
+only re-export from the crate root types that exist in the standard Bitcoin vernacular i.e., for
+pubkey you can `use bitcoin::PublicKey` but to get an x-only pubkey you need to go to the `key`
+module `use bitcoin::key::XOnlyPublicKey`.
+
+Please note this is still work-in-progress, suggestions welcome.
+
+## Code moves
+
+We moved _a lot_ of stuff around. This was a precursor to crate smashing which we have now started.
+Hopefully things are in intuitive places, it might be useful to take a quick look at the new
+module structure to get a feel for things, specifically:
+
+- We have a workspace now! The main crate now lives in `bitcoin/`. The `bitcoin_hashes` repository
+ has been merged into the `rust-bitcoin` repository and now lives under `hashes/`.
+
+- The `util` module is all but gone, try just removing `util::` at first, most modules are
+ re-exported at the crate root.
+
+- Cryptography related stuff can now primarily be found in 4 modules (`ecdsa`, `taproot`, `sighash`,
+ `key`). We have started to break ECDSA stuff up into legacy and segwit v0 where it is cleaner but
+ this is still work-in-progress.
+
+- Some hash wrapper types are now to be found in the module that they are used in e.g.,
+ `TapLeafHash` is in the `taproot` module. Others are still in `hash_types` but the re-exports now
+ conform to the aim stated above so you might need to add `hash_types::` to your paths for the more
+ esoteric hash types.
+
+## Script changes
+
+To optimize efficiency of working with borrowed scripts we renamed `Script` to `ScriptBuf` and added
+an unsized `Script`. It works just like `PathBuf` and `Path` (and other such types) from `std`. The
+API tries to resemble those types as much as reasonable (deref coercions etc.), so it should be
+intuitive. Methods in the library that previously took `&Script` (which is now `ScriptBuf`) take the
+unsized `&Script` now.
+
+Additionally, we changed the type accepted by the `push_slice` method to be another unsized newtype:
+`PushBytes` and it's owned counterpart `PushBytesBuf`. These types maintain the invariant of storing
+at most 2^32-1 bytes - the maximum one can push into script. Previously the method would panic if
+you attempted to do it (and it wasn't documented, sorry about that). Now you can either handle it
+explicitly using `TryFrom` or just pass a known-length array (implemented for arrays up to 73
+bytes).
+
+Types that are commonly pushed into script (serialized signatures, public keys...) implement
+`AsRef` so you can pass those directly as well. You can also implement `AsRef` for your
+types so they can be pushed directly.
+
+## Taproot changes
+
+Since the introduction of Taproot support the API got "stress tested" and various issues were
+uncovered and fixed. One of them is that the name "Branch Hash" refers to the algorithm being used
+to compute the value but the resulting value is actually a node in the tree. Thus we renamed
+`TapBranchHash` to `TapNodeHash` to reflect this. Additionally we originally used raw
+`sha256::Hashes` for node hashes which was error-prone and annoying because of manual conversions.
+We changed them to use `TapNodeHash` instead.
+
+When writing smart contracts that have their taproot trees statically known it was annoying to use
+`TaprootMerkleBranch::try_from` for arrays that are statically known to be shorter than 128. We've
+added `From` conversion for these.
+
+`NodeInfo` got some improvements too. For trees that are statically guaranteed to not have hidden
+nodes we have `TapTree` type and both got methods for getting an iterator over their respective
+items. This also improved our code internally, fixing some bugs and decreasing the risk of other
+bugs. We have some additional ideas to improve it further.
+
+Some types that do not have a well-defined serialization in the Bitcoin ecosystem or are purely Rust
+constructs (e.g. builders) got serde support removed. Serializing these would be error-prone and
+difficult to support stably. You can instead (de)serialize other types and convert them.
+
+Overall, these changes should make working with Taproot less error-prone and more ergonomic. Taproot
+is still young technology so it's possible there will be more changes in the future as new users try
+out the API. Please let us know if you have questions or suggestions.
+
+## Sighash
+
+We moved around and renamed a bunch of types to do with sighashes. In the `sighash` module, along
+with the `SighashCache` we now have the hopefully clearly named:
+
+- `LegacySighash`
+- `SegwitV0Sighash`
+- `TapSighash`
+- `EcdsaSighashType`
+- `TapSighashType`
+
+Signatures are now in their respective modules (`ecdsa` for legacy and segwit v0):
+
+- `taproot::Signature`
+- `ecdsa::Signature`
+
+## Lock types
+
+There are now two lock times, one for absolute locks (CLTV) and one for relative locks (CSV). We
+export the `absolute` and `relative` modules at the crate root so you can either import them from
+there or `use bitcoin::locktime::{absolute, relative};` if that's clearer. We expect locks to be
+used as `absolute::LockTime`.
+
+## Address changes
+
+Bitcoin addresses for different networks are different, up until this release, when parsing an
+address from a string, a check that the address format matched up to the expected network (e.g. "bc1"
+prefix for Bitcoin mainnet segwit addresses) was available but easy to forget. We've attempted to
+improve the API to make such omissions harder.
+
+Now `Address` includes a generic that is used as a marker for whether the address has been
+checked as valid for a particular network, we have `Address` and
+`Address`, defaulting to `NetworkChecked`. Because of the default some uses will
+just keep working but you should be aware that `Address` now means `Address`. The
+string parsing functions return types as expected. See the docs on `Address` for more information.
+
+## Newtypes
+
+This is a non-exhaustive list of newtypes added this release:
+
+- `relative::LockTime`
+- `relative::Height`
+- `relative::Time`
+- `ecdsa::SerializedSignature`
+- `ScriptBuf`
+- `PushBytes` / `PushBytesBuf`
+- `Target`
+- `CompactTarget`
+- `Work`
+
+### Renames
+
+This is a non-exhaustive list of types renamed in this release:
+
+- `Script` -> `ScriptBuf`
+- `locktime::LockTime` -> `locktime::absolute::LockTime`
+- `locktime::Time` -> `locktime::absolute::Time`
+- `locktime::Height` -> `locktime::absolute::Height`
+- `TapBranchHash` / `TapLeafHash` -> `TapNodeHash`
+- `TapSighashHash` -> `TapSighash`
+- `SchnorrSighashtype` -> `TapSighashType`
+- `schnorr` -> `taproot` (module rename)
+- Various error types were renamed, we try to use `foo::Error` if there is a single error type in
+ the `foo` module.
+
+### Removed types
+
+- `PackedLockTime`
+
+This type was intended as an optimization of the absolute locktime using a `u32`, this turned out to
+be not such a great idea. Please note `absolute::LockTime` does not implement `Ord`.
+
+- `Uint256`
+
+We changed the `Uint256` type to `U256` and made it private since it is not a general purpose
+integer type. Rather we wrapped it to create the `Work` and `Target` types.
+
+## Final thoughts
+
+I've tried to give you some context on why so many changes. Hopefully the context makes the upgrade
+path easier and helps to clarify the direction we are pushing in at the moment. As always,
+contributions are most welcome, issues, PRs, and even just ideas. We are here to provide the best
+crate we can for devs wishing to interact with the Bitcoin network in Rust, feedback from your
+usecase helps us a lot, help us out so we can help you.
+
+Thanks,
+Tobin (and the rust-bitcoin devs).