reset theme to https://github.com/onwidget/astrowind
Signed-off-by: Loïc Dachary <loic@dachary.org>
|
@ -12,4 +12,4 @@ insert_final_newline = true
|
|||
trim_trailing_whitespace = false
|
||||
|
||||
[{.*,*.md,*.json,*.toml,*.yml,}]
|
||||
indent_style = space
|
||||
indent_style = space
|
|
@ -1,2 +1,3 @@
|
|||
dist
|
||||
node_modules
|
||||
.github
|
2
.npmrc
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Expose Astro dependencies for `pnpm` users
|
||||
shamefully-hoist=true
|
|
@ -1,3 +1,4 @@
|
|||
dist
|
||||
node_modules
|
||||
.github
|
||||
.changeset
|
6
.stackblitzrc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"startCommand": "npm start",
|
||||
"env": {
|
||||
"ENABLE_CJS_IMPORTS": true
|
||||
}
|
||||
}
|
10
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"astro-build.astro-vscode",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"unifiedjs.vscode-mdx"
|
||||
],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
13
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"astro", // Enable .astro
|
||||
"typescript", // Enable .ts
|
||||
"typescriptreact" // Enable .tsx
|
||||
],
|
||||
"prettier.documentSelectors": ["**/*.astro"],
|
||||
"[astro]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
684
LICENSE.md
|
@ -1,660 +1,24 @@
|
|||
### GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
<https://fsf.org/>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed.
|
||||
|
||||
### Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains
|
||||
free software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing
|
||||
under this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
### TERMS AND CONDITIONS
|
||||
|
||||
#### 0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds
|
||||
of works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of
|
||||
an exact copy. The resulting work is called a "modified version" of
|
||||
the earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user
|
||||
through a computer network, with no transfer of a copy, is not
|
||||
conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices" to
|
||||
the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
#### 1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work for
|
||||
making modifications to it. "Object code" means any non-source form of
|
||||
a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users can
|
||||
regenerate automatically from other parts of the Corresponding Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that same
|
||||
work.
|
||||
|
||||
#### 2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not convey,
|
||||
without conditions so long as your license otherwise remains in force.
|
||||
You may convey covered works to others for the sole purpose of having
|
||||
them make modifications exclusively for you, or provide you with
|
||||
facilities for running those works, provided that you comply with the
|
||||
terms of this License in conveying all material for which you do not
|
||||
control copyright. Those thus making or running the covered works for
|
||||
you must do so exclusively on your behalf, under your direction and
|
||||
control, on terms that prohibit them from making any copies of your
|
||||
copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under the
|
||||
conditions stated below. Sublicensing is not allowed; section 10 makes
|
||||
it unnecessary.
|
||||
|
||||
#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such
|
||||
circumvention is effected by exercising rights under this License with
|
||||
respect to the covered work, and you disclaim any intention to limit
|
||||
operation or modification of the work as a means of enforcing, against
|
||||
the work's users, your or third parties' legal rights to forbid
|
||||
circumvention of technological measures.
|
||||
|
||||
#### 4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
#### 5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these
|
||||
conditions:
|
||||
|
||||
- a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
- b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under
|
||||
section 7. This requirement modifies the requirement in section 4
|
||||
to "keep intact all notices".
|
||||
- c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
- d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
#### 6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms of
|
||||
sections 4 and 5, provided that you also convey the machine-readable
|
||||
Corresponding Source under the terms of this License, in one of these
|
||||
ways:
|
||||
|
||||
- a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
- b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the Corresponding
|
||||
Source from a network server at no charge.
|
||||
- c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
- d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
- e) Convey the object code using peer-to-peer transmission,
|
||||
provided you inform other peers where the object code and
|
||||
Corresponding Source of the work are being offered to the general
|
||||
public at no charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal,
|
||||
family, or household purposes, or (2) anything designed or sold for
|
||||
incorporation into a dwelling. In determining whether a product is a
|
||||
consumer product, doubtful cases shall be resolved in favor of
|
||||
coverage. For a particular product received by a particular user,
|
||||
"normally used" refers to a typical or common use of that class of
|
||||
product, regardless of the status of the particular user or of the way
|
||||
in which the particular user actually uses, or expects or is expected
|
||||
to use, the product. A product is a consumer product regardless of
|
||||
whether the product has substantial commercial, industrial or
|
||||
non-consumer uses, unless such uses represent the only significant
|
||||
mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to
|
||||
install and execute modified versions of a covered work in that User
|
||||
Product from a modified version of its Corresponding Source. The
|
||||
information must suffice to ensure that the continued functioning of
|
||||
the modified object code is in no case prevented or interfered with
|
||||
solely because modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or
|
||||
updates for a work that has been modified or installed by the
|
||||
recipient, or for the User Product in which it has been modified or
|
||||
installed. Access to a network may be denied when the modification
|
||||
itself materially and adversely affects the operation of the network
|
||||
or violates the rules and protocols for communication across the
|
||||
network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
#### 7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders
|
||||
of that material) supplement the terms of this License with terms:
|
||||
|
||||
- a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
- b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
- c) Prohibiting misrepresentation of the origin of that material,
|
||||
or requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
- d) Limiting the use for publicity purposes of names of licensors
|
||||
or authors of the material; or
|
||||
- e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
- f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions
|
||||
of it) with contractual assumptions of liability to the recipient,
|
||||
for any liability that these contractual assumptions directly
|
||||
impose on those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions; the
|
||||
above requirements apply either way.
|
||||
|
||||
#### 8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your license
|
||||
from a particular copyright holder is reinstated (a) provisionally,
|
||||
unless and until the copyright holder explicitly and finally
|
||||
terminates your license, and (b) permanently, if the copyright holder
|
||||
fails to notify you of the violation by some reasonable means prior to
|
||||
60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
#### 9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or run
|
||||
a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
#### 10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
#### 11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims owned
|
||||
or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within the
|
||||
scope of its coverage, prohibits the exercise of, or is conditioned on
|
||||
the non-exercise of one or more of the rights that are specifically
|
||||
granted under this License. You may not convey a covered work if you
|
||||
are a party to an arrangement with a third party that is in the
|
||||
business of distributing software, under which you make payment to the
|
||||
third party based on the extent of your activity of conveying the
|
||||
work, and under which the third party grants, to any of the parties
|
||||
who would receive the covered work from you, a discriminatory patent
|
||||
license (a) in connection with copies of the covered work conveyed by
|
||||
you (or copies made from those copies), or (b) primarily for and in
|
||||
connection with specific products or compilations that contain the
|
||||
covered work, unless you entered into that arrangement, or that patent
|
||||
license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
#### 12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under
|
||||
this License and any other pertinent obligations, then as a
|
||||
consequence you may not convey it at all. For example, if you agree to
|
||||
terms that obligate you to collect a royalty for further conveying
|
||||
from those to whom you convey the Program, the only way you could
|
||||
satisfy both those terms and this License would be to refrain entirely
|
||||
from conveying the Program.
|
||||
|
||||
#### 13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your
|
||||
version supports such interaction) an opportunity to receive the
|
||||
Corresponding Source of your version by providing access to the
|
||||
Corresponding Source from a network server at no charge, through some
|
||||
standard or customary means of facilitating copying of software. This
|
||||
Corresponding Source shall include the Corresponding Source for any
|
||||
work covered by version 3 of the GNU General Public License that is
|
||||
incorporated pursuant to the following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
#### 14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Affero General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever
|
||||
published by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future versions
|
||||
of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
#### 15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
|
||||
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
|
||||
DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||
CORRECTION.
|
||||
|
||||
#### 16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
|
||||
CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
|
||||
NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
|
||||
LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
|
||||
TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
|
||||
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
#### 17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
### How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these
|
||||
terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to
|
||||
attach them to the start of each source file to most effectively state
|
||||
the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper
|
||||
mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for
|
||||
the specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. For more information on this, and how to apply and follow
|
||||
the GNU AGPL, see <https://www.gnu.org/licenses/>.
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the authors (onWidget)
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
||||
|
|
24
Makefile
|
@ -1,24 +0,0 @@
|
|||
install:
|
||||
npm install
|
||||
|
||||
dev:
|
||||
npm run dev
|
||||
|
||||
node_modules:
|
||||
# For use by the CI
|
||||
npm ci
|
||||
|
||||
build: node_modules
|
||||
npm run build
|
||||
|
||||
prod-preview:
|
||||
npm run preview
|
||||
|
||||
publish: build
|
||||
# This is called by a publish.sh script which contains the following line:
|
||||
# SRHT_SITE=username.srht.site SRHT_TOKEN=s3cr3t make publish
|
||||
# The token needs the scope pages.sr.ht:PAGES (read+write)
|
||||
cd dist && tar -cvz . > ../public.tar.gz
|
||||
curl --oauth2-bearer $$SRHT_TOKEN \
|
||||
-Fcontent=@public.tar.gz \
|
||||
https://pages.sr.ht/publish/$$SRHT_SITE
|
262
README.md
|
@ -1,80 +1,250 @@
|
|||
# Website for Forgejo
|
||||
# 🚀 AstroWind
|
||||
|
||||
The website is build with [Astro](https://astro.build).
|
||||
<img src="lighthouse-score.png" align="right"
|
||||
alt="AstroWind Lighthouse Score" width="100" height="358">
|
||||
|
||||
## Project Structure
|
||||
**AstroWind** is a free and open-source template to make your website using **Astro + Tailwind CSS**. Ready to start a new project and designed taking into account best practices.
|
||||
|
||||
## Features
|
||||
|
||||
- ✅ Integration with **Tailwind CSS** ([@astrojs/tailwind](https://docs.astro.build/en/guides/integrations-guide/tailwind/)) supporting **Dark mode**.
|
||||
- ✅ **Production-ready** scores in [Lighthouse](https://web.dev/measure/) and [PageSpeed Insights](https://pagespeed.web.dev/) reports.
|
||||
- ✅ **Fast and SEO friendly blog** with automatic **RSS feed** ([@astrojs/rss](https://docs.astro.build/en/guides/rss/)), [**MDX** support](https://docs.astro.build/en/guides/integrations-guide/mdx/), **Categories & Tags**, **Social Share** buttons, ...
|
||||
- ✅ **Image optimization** ([@astrojs/images](https://docs.astro.build/en/guides/integrations-guide/image/)) and **Font optimization**.
|
||||
- ✅ Generation of **project sitemap** based on your routes ([@astrojs/sitemap](https://docs.astro.build/en/guides/integrations-guide/sitemap/)).
|
||||
- ✅ **Open Graph tags** for social media sharing.
|
||||
- ✅ **Analytics** built-in Google Analytics, and Splitbee integration.
|
||||
|
||||
<br>
|
||||
|
||||
<img src="./screenshot.jpg" alt="AstroWind Theme Screenshot">
|
||||
|
||||
[](https://onwidget.com)
|
||||
[](https://github.com/onwidget/astrowind/blob/main/LICENSE.md)
|
||||
[](https://github.com/onwidget)
|
||||
[](https://github.com/onwidget/astrowind#contributing)
|
||||
[](https://snyk.io/test/github/onwidget/astrowind)
|
||||
[](https://github.com/onwidget/astrowind)
|
||||
[](https://github.com/onwidget/astrowind)
|
||||
|
||||
<br>
|
||||
|
||||
<details open>
|
||||
<summary>Table of Contents</summary>
|
||||
|
||||
- [Demo](#demo)
|
||||
- [Getting started](#getting-started)
|
||||
- [Project structure](#project-structure)
|
||||
- [Commands](#commands)
|
||||
- [Configuration](#configuration)
|
||||
- [Deploy](#deploy)
|
||||
- [Roadmap](#roadmap)
|
||||
- [Frequently Asked Questions](#frequently-asked-questions)
|
||||
- [Contributing](#contributing)
|
||||
- [Acknowledgements](#acknowledgements)
|
||||
- [License](#license)
|
||||
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
## Demo
|
||||
|
||||
📌 [https://astrowind.vercel.app/](https://astrowind.vercel.app/)
|
||||
|
||||
<br>
|
||||
|
||||
## Getting started
|
||||
|
||||
**AstroWind** tries to give you quick access to creating a website using [Astro](https://astro.build/) + [Tailwind CSS](https://tailwindcss.com/). It's a free theme focuses on simplicity, good practices and high performance.
|
||||
|
||||
Very little vanilla javascript is used only to provide basic functionality so that each developer decides which framework (React, Vue, Svelte, Solid JS...) to use and how to approach their goals..
|
||||
|
||||
### Project structure
|
||||
|
||||
Inside AstroWind template, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
/
|
||||
├── data/
|
||||
| └── blog/
|
||||
| ├── post-slug-1.md
|
||||
| ├── post-slug-2.mdx
|
||||
| └── ...
|
||||
├── public/
|
||||
│ └── favicon.svg
|
||||
│ ├── robots.txt
|
||||
│ └── favicon.ico
|
||||
├── src/
|
||||
│ ├── assets/
|
||||
│ │ ├── images/
|
||||
| | └── styles/
|
||||
| | └── base.css
|
||||
│ ├── components/
|
||||
│ │ └── Card.astro
|
||||
│ │ ├── atoms/
|
||||
│ │ ├── blog/
|
||||
│ │ ├── core/
|
||||
| | └── widgets/
|
||||
| | ├── Header.astro
|
||||
| | ├── Footer.astro
|
||||
| | └── ...
|
||||
│ ├── layouts/
|
||||
│ │ └── Layout.astro
|
||||
│ └── pages/
|
||||
│ ├── index.astro
|
||||
│ └── code-of-conduct.md
|
||||
└── package.json
|
||||
│ | |── BaseLayout.astro
|
||||
│ | └── ...
|
||||
│ ├── pages/
|
||||
│ | ├── [...blog]/
|
||||
| | | ├── [...page].astro
|
||||
| | | └── [slug].astro
|
||||
│ | ├── [...categories]/
|
||||
| | | └── [category]/
|
||||
| | | └── [...page].astro
|
||||
│ | ├── [...tags]/
|
||||
| | | └── [tag]/
|
||||
| | | └── [...page].astro
|
||||
│ | ├── index.astro
|
||||
| | ├── 404.astro
|
||||
| | └-- rss.xml.js
|
||||
│ ├── utils/
|
||||
│ └── config.mjs
|
||||
├── package.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name, with a _trailing slash_.
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
Any static assets, like images, can be placed in the `public/` directory if they do not require any transformation or in the `assets/` directory if they are imported directly.
|
||||
|
||||
## Commands
|
||||
[](https://githubbox.com/onwidget/astrowind/tree/main)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Update `config.mjs` and contents. Have fun!
|
||||
|
||||
<br>
|
||||
|
||||
### Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :--------------------- | :------------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro preview` |
|
||||
| `npm run astro --help` | Get help using the Astro CLI |
|
||||
| Command | Action |
|
||||
| :-------------------- | :------------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run format` | Format codes with Prettier |
|
||||
| `npm run lint:eslint` | Run Eslint |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro preview` |
|
||||
|
||||
## Styling
|
||||
<br>
|
||||
|
||||
The styling is achieved using [Tailwind CSS](https://tailwindcss.com/). Custom classes can be added to `src/style.css`.
|
||||
### Configuration
|
||||
|
||||
The standard layout is implemented in `src/layouts/Layout.astro` (see neighbour files for other layouts).
|
||||
Basic configuration file: `./src/config.mjs`
|
||||
|
||||
## Continuous deployment
|
||||
```javascript
|
||||
export const SITE = {
|
||||
name: 'Example',
|
||||
|
||||
The `main` branch triggers a Woodpecker build (see `.woodpecker.yml`), which pushes the "compiled" files to https://forgejo.org.
|
||||
origin: 'https://example.com',
|
||||
basePathname: '/', // Change this if you need to deploy to Github Pages, for example
|
||||
trailingSlash: false, // Generate permalinks with or without "/" at the end
|
||||
|
||||
In addition, each branch is pushed to https://codeberg.org/forgejo/pages, which is accessible for preview via:
|
||||
title: 'Example - This is the homepage title of Example',
|
||||
description: 'This is the homepage description of Example',
|
||||
|
||||
* https://forgejo.codeberg.page/ for the `main` branch
|
||||
* https://forgejo.codeberg.page/@foobar for the `foobar` branch
|
||||
googleAnalyticsId: false, // or "G-XXXXXXXXXX",
|
||||
googleSiteVerificationId: false, // or some value,
|
||||
};
|
||||
|
||||
The shared user https://codeberg.org/forgejo-website with email website@forgejo.org has write permissions to https://codeberg.org/forgejo/pages and the CI relies an application token from this user to push the pages.
|
||||
export const BLOG = {
|
||||
disabled: false,
|
||||
postsPerPage: 4,
|
||||
|
||||
## Hosting
|
||||
blog: {
|
||||
disabled: false,
|
||||
pathname: 'blog', // blog main path, you can change this to "articles" (/articles)
|
||||
},
|
||||
|
||||
* url: https://uberspace.de/
|
||||
* user: forgejo
|
||||
* password is shared by Forgejo secret keepers
|
||||
post: {
|
||||
disabled: false,
|
||||
pathname: '', // empty for /some-post, value for /pathname/some-post
|
||||
},
|
||||
|
||||
### DNS
|
||||
category: {
|
||||
disabled: false,
|
||||
pathname: 'category', // set empty to change from /category/some-category to /some-category
|
||||
},
|
||||
|
||||
* Get IPv4/IPv6 at https://dashboard.uberspace.de/dashboard/datasheet
|
||||
* Set forgejo.org & www.forgejo.org A & AAAA records at https://www.ovh.com/manager/#/web/zone/forgejo.org
|
||||
* ssh forgejo@atria.uberspace.de # as per https://manual.uberspace.de/web-domains/#setup
|
||||
* uberspace web domain add forgejo.org
|
||||
* uberspace web domain add www.forgejo.org
|
||||
tag: {
|
||||
disabled: false,
|
||||
pathname: 'tag', // set empty to change from /tag/some-tag to /some-tag
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### CI
|
||||
<br>
|
||||
|
||||
* Set SSH password at
|
||||
* Add secret **sshpass** to https://ci.codeberg.org/forgejo/website/settings#secrets
|
||||
* The [publish Woodpecker CI pipeline](.woodpecker.yml) builds and rsync to the host
|
||||
### Deploy
|
||||
|
||||
## Want to learn more?
|
||||
#### Deploy to production (manual)
|
||||
|
||||
Feel free to check [the documentation of Astro](https://docs.astro.build).
|
||||
You can create an optimized production build with:
|
||||
|
||||
```shell
|
||||
npm run build
|
||||
```
|
||||
|
||||
Now, your website is ready to be deployed. All generated files are located at
|
||||
`dist` folder, which you can deploy the folder to any hosting service you
|
||||
prefer.
|
||||
|
||||
#### Deploy to Netlify
|
||||
|
||||
Clone this repository on own GitHub account and deploy to Netlify:
|
||||
|
||||
[](https://app.netlify.com/start/deploy?repository=https://github.com/onwidget/astrowind)
|
||||
|
||||
#### Deploy to Vercel
|
||||
|
||||
Clone this repository on own GitHub account and deploy to Vercel:
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fonwidget%2Fastrowind)
|
||||
|
||||
<br>
|
||||
|
||||
## Roadmap
|
||||
|
||||
- _Project_:
|
||||
- Create simple and clear strategy to get template updates
|
||||
- _Blog_:
|
||||
- Improve blog design
|
||||
- Create component or utilities for related posts
|
||||
- Add more _shortcodes_ or _embed_ functions to posts in Markdown: (eg video, tweet...)
|
||||
- _More widgets_:
|
||||
- Add more Tailwind components useful for most scenarios (Features, Contact, Call to Actions, Content, FAQs ...)
|
||||
- Create external library or place with useful Tailwind components
|
||||
- _More Examples_: Add commonly used example pages (Ex: About, Terms, Services...)
|
||||
- _Documentation_: Create detailed documentation with best practices and redesign tips
|
||||
|
||||
<br>
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
- Why?
|
||||
-
|
||||
-
|
||||
|
||||
<br>
|
||||
|
||||
## Contributing
|
||||
|
||||
If you have any idea, suggestions or find any bugs, feel free to open a discussion, an issue or create a pull request.
|
||||
That would be very useful for all of us and we would be happy to listen and take action.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Initially created by [onWidget](https://onwidget.com) and maintained by a community of [contributors](https://github.com/onwidget/astrowind/graphs/contributors).
|
||||
|
||||
## License
|
||||
|
||||
**AstroWind** is licensed under the Unlicense license — see the [LICENSE](https://github.com/onwidget/astrowind/blob/main/LICENSE.md) file for details.
|
||||
|
|
|
@ -1,29 +1,58 @@
|
|||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
import image from '@astrojs/image';
|
||||
import mdx from '@astrojs/mdx';
|
||||
import partytown from '@astrojs/partytown';
|
||||
|
||||
import mdPrefixWithBase from './src/md-prefix-with-base';
|
||||
import { remarkReadingTime } from './src/utils/frontmatter.mjs';
|
||||
import { SITE } from './src/config.mjs';
|
||||
|
||||
const base = '/';
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const remarkPlugins = [];
|
||||
if (base != '/') {
|
||||
remarkPlugins.push([mdPrefixWithBase, base]);
|
||||
}
|
||||
const whenExternalScripts = (items = []) =>
|
||||
SITE.googleAnalyticsId ? (Array.isArray(items) ? items.map((item) => item()) : [items()]) : [];
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'https://forgejo.codeberg.page', // TODO: update with correct URL on prod (needed for for sitemap and canonical URLs final build)
|
||||
base,
|
||||
trailingSlash: 'always',
|
||||
site: SITE.origin,
|
||||
base: SITE.basePathname,
|
||||
trailingSlash: SITE.trailingSlash ? 'always' : 'never',
|
||||
|
||||
output: 'static',
|
||||
|
||||
integrations: [
|
||||
tailwind({
|
||||
config: {
|
||||
applyBaseStyles: false,
|
||||
},
|
||||
}),
|
||||
sitemap(),
|
||||
image({
|
||||
serviceEntryPoint: '@astrojs/image/sharp',
|
||||
}),
|
||||
mdx(),
|
||||
|
||||
...whenExternalScripts(() =>
|
||||
partytown({
|
||||
config: { forward: ['dataLayer.push'] },
|
||||
})
|
||||
),
|
||||
],
|
||||
|
||||
markdown: {
|
||||
remarkPlugins: [remarkReadingTime],
|
||||
extendDefaultPlugins: true,
|
||||
remarkPlugins,
|
||||
},
|
||||
|
||||
vite: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'~': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
0
data/.gitkeep
Normal file
45
data/blog/astrowind-template-in-depth.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
publishDate: 'Aug 08 2022'
|
||||
title: 'AstroWind template in depth'
|
||||
description: 'Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti.'
|
||||
image: '~/assets/images/old.jpg'
|
||||
category: 'Tutorials'
|
||||
tags: [astro, tailwind css, front-end]
|
||||
canonical: https://astrowind.vercel.app/astrowind-template-in-depth # When posting content to multiple platforms at the same time (such as this website and Medium) and want to specify the ultimate authority. Remove it to automatically generate canonical
|
||||
---
|
||||
|
||||
## Dictum integer fusce ac ridiculus et odio sollicitudin diam at
|
||||
|
||||
Lorem ipsum dolor sit amet consectetur adipiscing elit euismod rutrum, consequat fringilla ultricies nullam curae mollis semper conubia viverra, orci aenean dapibus pharetra nec tortor tellus cubilia. Ullamcorper mi lectus eu malesuada tempor massa praesent magna mattis posuere, lobortis vulputate ut duis magnis parturient habitant nibh id tristique, quis suspendisse donec nisl penatibus sem non feugiat taciti. Mollis per ridiculus integer cursus semper vestibulum fermentum penatibus cubilia blandit scelerisque, tempus platea leo posuere ac pharetra volutpat aliquet euismod id ullamcorper lobortis, urna est magna mus rhoncus massa curae libero praesent eget. Mattis malesuada vestibulum quis ac nam phasellus suscipit facilisis libero diam posuere, cursus massa vehicula neque imperdiet tincidunt dui egestas lacinia mollis aliquet orci, nisl curabitur dapibus litora dis cum nostra montes ligula praesent. Facilisi aliquam convallis molestie tempor blandit ultricies bibendum parturient cubilia quam, porttitor morbi torquent tempus taciti nec faucibus elementum phasellus, quis inceptos vestibulum gravida augue potenti eget nunc maecenas. Tempor facilisis ligula volutpat habitant consequat inceptos orci per potenti blandit platea, mus sapien eget vel libero vestibulum augue cubilia ut ultrices fringilla lectus, imperdiet pellentesque cum ridiculus convallis sollicitudin nisl interdum semper felis.
|
||||
|
||||
Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti augue nulla vivamus senectus odio, quisque curabitur enim consequat class sociis feugiat ullamcorper, felis dis imperdiet cubilia commodo sed massa phasellus. Viverra purus mus nisi condimentum dui vehicula facilisis turpis, habitant nascetur lectus tempor quisque habitasse urna scelerisque, nibh nullam vestibulum luctus aenean mollis metus. Suscipit gravida duis nec aliquet natoque molestie a ridiculus scelerisque cum, justo cursus sapien sodales purus dignissim vel facilisi magnis, inceptos rutrum ut integer auctor commodo sollicitudin fames et. Faucibus ligula nibh sagittis mauris auctor posuere habitant, scelerisque phasellus accumsan egestas gravida viverra nam, sed etiam eleifend proin massa dictumst. Porttitor risus luctus per aenean tellus primis fringilla vitae fames lacinia mauris metus, nec pulvinar quisque commodo sodales ac nibh natoque phasellus semper placerat. Lectus aenean potenti leo sollicitudin tristique eros quam ligula, vestibulum diam consequat enim torquent nec tempus, blandit viverra dapibus eleifend dis nunc nascetur.
|
||||
|
||||
## Sodales hendrerit malesuada et vestibulum
|
||||
|
||||
- Luctus euismod pretium nisi et, est dui enim.
|
||||
|
||||
- Curae eget inceptos malesuada, fermentum class.
|
||||
|
||||
- Porttitor vestibulum aliquam porta feugiat velit, potenti eu placerat.
|
||||
|
||||
- Ligula lacus tempus ac porta, vel litora.
|
||||
|
||||
Torquent non nisi lacinia faucibus nibh tortor taciti commodo porttitor, mus hendrerit id leo scelerisque mollis habitasse orci tristique aptent, lacus at molestie cubilia facilisis porta accumsan condimentum. Metus lacus suscipit porttitor integer facilisi torquent, nostra nulla platea at natoque varius venenatis, id quam pharetra aliquam leo. Dictum orci himenaeos quam mi fusce lacinia maecenas ac magna eleifend laoreet, vivamus enim curabitur ullamcorper est ultrices convallis suscipit nascetur. Ornare fames pretium ante ac eget nisi tellus vivamus, convallis mauris sapien imperdiet sollicitudin aliquet taciti quam, lacinia tempor primis magna iaculis at eu. Est facilisi proin risus eleifend orci torquent ultricies platea, quisque nullam vel porttitor euismod sociis non, maecenas sociosqu interdum arcu sed pharetra potenti. Aliquet risus tempus hendrerit sapien tellus eget cursus enim etiam dui, lobortis nostra pellentesque odio posuere morbi ad neque senectus arcu eu, turpis proin ac felis purus fames magnis dis dignissim.
|
||||
|
||||
Orci volutpat augue viverra scelerisque dictumst ut condimentum vivamus, accumsan cum sem sollicitudin aliquet vehicula porta pretium placerat, malesuada euismod primis cubilia rutrum tempus parturient. Urna mauris in nibh morbi hendrerit vulputate condimentum, iaculis consequat porttitor dui dis euismod eros, arcu elementum venenatis varius lectus nisi. Nibh arcu ultrices semper morbi quam aptent quisque porta posuere iaculis, vestibulum cum vitae primis varius natoque conubia eu. Placerat sociis sagittis sociosqu morbi purus lobortis convallis, bibendum tortor ridiculus orci habitasse viverra dictum, quis rutrum fusce potenti volutpat vehicula. Curae porta inceptos lectus mus urna litora semper aliquam libero rutrum sem dui maecenas ligula quis, eget risus non imperdiet cum morbi magnis suspendisse etiam augue porttitor placerat facilisi hendrerit. Et eleifend eget augue duis fringilla sagittis erat est habitasse commodo tristique quisque pretium, suspendisse imperdiet inceptos mollis blandit magna mus elementum molestie sed vestibulum. Euismod morbi hendrerit suscipit felis ornare libero ligula, mus tortor urna interdum blandit nisi netus posuere, purus fermentum magnis nam primis nulla.
|
||||
|
||||
## Elementum nisi urna cursus nisl quam ante tristique blandit ultricies eget
|
||||
|
||||
Netus at rutrum taciti vestibulum molestie conubia semper class potenti lobortis, hendrerit donec vitae ad libero natoque parturient litora congue. Torquent rhoncus odio cursus iaculis molestie arcu leo condimentum accumsan, laoreet congue duis libero justo tortor commodo fusce, massa eros hac euismod netus sodales mi magnis. Aenean nullam sollicitudin ad velit nulla venenatis suspendisse iaculis, aliquet senectus mollis aptent fringilla volutpat nascetur, nec urna vehicula lacinia neque augue orci. Suspendisse et eleifend convallis sollicitudin posuere diam turpis gravida congue ultrices, laoreet ultricies dapibus proin facilisis magna class praesent fusce. Mus morbi magnis ultricies sed turpis ultrices tempus tortor bibendum, netus nulla viverra torquent malesuada ridiculus tempor. Parturient sociosqu erat ullamcorper gravida natoque varius, etiam habitant augue praesent per curabitur iaculis, donec pellentesque cursus suscipit aliquet. Congue curae cursus scelerisque pellentesque quis fusce arcu eros dictumst luctus ridiculus nisl viverra, turpis class faucibus phasellus feugiat eleifend fringilla orci tristique habitasse conubia quam. Habitasse montes congue sodales rutrum cras torquent cursus auctor condimentum imperdiet egestas nascetur, platea tincidunt ut sollicitudin purus libero lobortis ad nisi diam quam.
|
||||
|
||||
Venenatis suscipit class iaculis non velit ultrices ligula nulla mattis turpis erat, enim montes sapien rhoncus tincidunt scelerisque fermentum dapibus imperdiet risus, tempor est massa pretium at molestie morbi nec libero aptent. Morbi rhoncus massa accumsan a pharetra nec conubia at, sem justo sociis suspendisse aenean dis magna, parturient inceptos ad vestibulum lectus ullamcorper ante. In condimentum suscipit iaculis suspendisse nisl gravida risus sociis, cursus nec lectus per tristique phasellus imperdiet ultrices taciti, natoque sociosqu curae tellus hendrerit feugiat dignissim. Risus est fringilla elementum ullamcorper nibh urna sociosqu quis, netus eu mollis torquent ridiculus nisi et, sodales cum vulputate augue facilisis egestas vel. Ridiculus volutpat nisi netus venenatis vitae posuere purus, nec aliquam fusce nascetur mus iaculis, sociosqu sodales erat id tempor malesuada. Lacinia platea sagittis tincidunt semper nam magna praesent, ante ornare senectus in ligula justo, id rhoncus nullam nec maecenas aliquam. Enim aenean rutrum magnis magna duis pulvinar curae posuere massa, dui orci class dis phasellus parturient aliquet luctus eget bibendum, ultricies fringilla erat purus habitasse natoque urna aliquam.
|
||||
|
||||
Cursus varius volutpat aliquam tellus blandit netus orci, augue eleifend molestie cubilia proin. Sagittis enim nam hendrerit risus sem laoreet commodo interdum, odio fames et nunc bibendum urna conubia cursus neque, arcu accumsan nascetur ridiculus cubilia vestibulum sapien. Luctus maecenas accumsan turpis donec dictum justo ridiculus consequat ad, habitant elementum litora magna sed rutrum tempus. Et dapibus eget feugiat dictum quam proin sem tincidunt lectus risus natoque, massa ut purus sollicitudin dignissim hac sed nibh facilisis arcu dis lacinia, cras fringilla erat sociis eleifend varius vestibulum nunc aenean neque. Penatibus curabitur aptent magna faucibus aliquam sed massa curae maecenas nibh, sodales montes nulla cursus litora justo suscipit ut neque, varius rutrum enim dignissim auctor velit luctus blandit nostra. Torquent lobortis nec volutpat aliquet vestibulum penatibus bibendum, eget platea a dictum mollis congue. Netus consequat eget cursus cubilia nostra quam etiam sollicitudin purus, imperdiet per bibendum proin duis felis montes ut tincidunt semper, ad vestibulum accumsan tortor fames potenti tristique praesent. Arcu mollis tempus tincidunt ad platea mauris, nec inceptos dis penatibus donec, primis taciti fermentum erat mi.
|
||||
|
||||
Lacinia pellentesque dui porttitor arcu mauris turpis quam vitae rutrum in vel, sociosqu ultricies ultrices rhoncus fames taciti ut aliquet placerat ligula. Nec libero aptent nisl euismod pellentesque curae posuere magnis, fusce condimentum augue fames penatibus mollis consequat, justo ullamcorper semper nibh netus turpis est. Condimentum nisi bibendum fames placerat habitasse curabitur facilisis accumsan sagittis ante, etiam id turpis aliquam elementum habitant eget aptent nisl, duis nullam velit hac cubilia risus ultricies interdum ultrices. A praesent taciti duis tempor sollicitudin primis auctor, consequat potenti porta iaculis ad imperdiet, habitasse sagittis quam eu mus nisl. Lacus morbi aptent fusce augue curae elementum diam litora leo condimentum pharetra facilisi eros, dis bibendum primis habitasse tempus porttitor dictumst potenti justo congue hendrerit curabitur. Pretium natoque penatibus pellentesque auctor, luctus libero pharetra proin vitae, habitant nam posuere. Tortor facilisis sed venenatis nostra massa congue lobortis rutrum ornare, ullamcorper libero nibh elementum dictumst torquent felis at, nam porttitor curabitur neque natoque accumsan hac id. Dictum aenean sed facilisis interdum libero eu, praesent curae purus ac platea, natoque penatibus malesuada erat faucibus.
|
||||
|
||||
Porta lobortis ad dapibus id vitae convallis litora vehicula molestie mattis aliquam, sociosqu nisi ridiculus netus faucibus platea aptent diam vivamus. Taciti tristique in erat ridiculus ad ultricies mollis risus, laoreet aliquam semper felis nam cubilia praesent, tempus nostra augue penatibus convallis proin quis. Lacus commodo senectus tempus suspendisse suscipit, class porttitor mi potenti at, vitae mattis a pharetra. At cras felis fermentum turpis sapien fames volutpat sollicitudin integer egestas ornare nunc, praesent mollis nibh quisque tristique vitae curae lobortis lacinia donec sagittis. Tincidunt enim morbi etiam malesuada odio laoreet lacinia, phasellus fringilla integer inceptos lobortis ridiculus suscipit massa, turpis leo molestie a mus conubia. Ridiculus magna fermentum sodales interdum posuere mi risus per rhoncus donec orci, pulvinar curabitur facilisis curae accumsan ligula scelerisque porta a porttitor, dignissim parturient facilisi felis quis malesuada litora convallis cum integer. Fringilla pulvinar consequat suspendisse aenean mollis interdum odio viverra aptent, nascetur eget magna facilisi erat fermentum turpis taciti ornare molestie, nam sollicitudin natoque gravida porta nulla rutrum condimentum.
|
||||
|
||||
Bibendum leo etiam porta fermentum donec mauris netus nibh per non varius diam, massa aliquam elementum lacinia himenaeos sem eros platea justo neque placerat. Etiam morbi ac magna quis gravida mi molestie praesent potenti pharetra id ornare euismod congue, est sapien iaculis rhoncus platea posuere litora integer mattis lacinia cubilia rutrum sem. Facilisis est tempus ridiculus ultricies faucibus nec aenean praesent ad vel penatibus, mus hac bibendum pretium rhoncus nascetur non neque mollis curabitur lacinia, consequat ut tortor aptent et sapien ornare quisque suspendisse vitae. Et suscipit nulla mauris integer nam elementum massa, purus pellentesque placerat magnis scelerisque leo metus, sociis interdum tincidunt ac ullamcorper feugiat. Magnis inceptos justo tincidunt ad etiam conubia ultricies tortor, metus congue ullamcorper turpis bibendum sociosqu cubilia curae urna, in phasellus pellentesque quam platea imperdiet accumsan. Urna vivamus ut bibendum diam sociis euismod rutrum, consequat magnis primis curae donec quis placerat conubia, semper mattis mollis auctor fringilla erat. Suspendisse phasellus gravida mollis eleifend nascetur dictum lectus dui fringilla pulvinar feugiat, venenatis lobortis posuere dictumst porttitor bibendum ullamcorper montes ultrices congue, scelerisque lacinia viverra suscipit vel natoque inceptos dignissim habitant laoreet.
|
||||
|
||||
Nascetur gravida mus imperdiet dapibus suspendisse cras nisl conubia, vulputate placerat senectus viverra nibh dictum et morbi pulvinar, cubilia ad non eleifend sagittis scelerisque penatibus. Auctor rutrum arcu phasellus tellus et magnis in, aliquet sociis fermentum class praesent aliquam lectus curabitur, natoque id pulvinar hac ultricies augue. Himenaeos commodo cum donec metus curae convallis sociis, facilisi lectus torquent fermentum rutrum vivamus non platea, nisl venenatis id ullamcorper mauris at. Facilisis etiam pharetra porta hendrerit eu conubia aliquam malesuada senectus, dui sociis penatibus integer mus quis turpis. Venenatis placerat ultricies tincidunt morbi himenaeos metus, diam curae aliquet neque pellentesque justo lobortis, cras sodales nam imperdiet parturient. Ligula potenti fringilla platea feugiat pulvinar dis habitant, nec nisl diam orci consequat condimentum gravida accumsan, massa vehicula euismod faucibus dignissim et. Scelerisque natoque vel eu proin etiam nostra pulvinar ullamcorper convallis facilisi, viverra vitae nunc penatibus ligula magnis cum senectus habitasse at, sagittis rhoncus faucibus netus nisl facilisis tristique parturient nulla. Condimentum massa lectus volutpat mollis curae eu, curabitur feugiat conubia mauris commodo mattis, magnis ad nullam ac sapien.
|
48
data/blog/get-started-website-with-astro-tailwind-css.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
publishDate: 'Aug 12 2022'
|
||||
title: 'Get started with AstroWind to create a website using Astro and Tailwind CSS'
|
||||
description: 'Lorem ipsum dolor sit amet'
|
||||
excerpt: 'Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat'
|
||||
image: '~/assets/images/steps.jpg'
|
||||
category: 'Tutorials'
|
||||
tags: [astro, tailwind css]
|
||||
canonical: https://astrowind.vercel.app/get-started-website-with-astro-tailwind-css # When posting content to multiple platforms at the same time (such as this website and Medium) and want to specify the ultimate authority. Remove it to automatically generate canonical
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
## Nostra torquent consequat volutpat aliquet neque
|
||||
|
||||
Lorem ipsum dolor sit amet consectetur adipiscing elit proin, aenean litora volutpat urna egestas magnis arcu non, cras ut cursus et sed morbi lectus. Integer faucibus sagittis eu nunc urna aliquet a laoreet torquent, suspendisse penatibus nulla sollicitudin congue rutrum dictum. Ornare mi habitasse fermentum phasellus dui et morbi litora sodales dictum id erat, nibh purus class ligula aenean lectus venenatis euismod cras torquent ac. Senectus sagittis conubia hendrerit at egestas porta venenatis nisi metus gravida tempor, aenean facilisis nisl ante facilisi lacus integer hac iaculis purus. Scelerisque libero torquent egestas curae tellus viverra inceptos imperdiet urna, porta suspendisse interdum primis odio morbi tempor commodo dictumst, suscipit ornare habitasse semper feugiat cras quisque lobortis.
|
||||
|
||||
Iaculis arcu commodo dis proin vitae himenaeos, ante tristique potenti magna ligula, sagittis libero fermentum ullamcorper sociis. Sem eros non arcu natoque fringilla lacus vestibulum lacinia integer mus viverra in proin, sagittis fusce tortor erat enim rutrum vulputate curae laoreet class diam. Inceptos convallis ac nisi natoque nam quisque magnis ut nullam fringilla curae, luctus lacus purus habitant erat magna molestie class habitasse metus, nibh lobortis tortor curabitur neque phasellus feugiat netus morbi parturient. Neque malesuada mauris justo himenaeos pharetra, ullamcorper enim ligula a nulla consequat, eget vivamus velit ridiculus.
|
||||
|
||||
## Praesent tellus ad sapien erat or
|
||||
|
||||
- Quam orci nostra mi nulla, hac a.
|
||||
|
||||
- Interdum iaculis quis tellus sociis orci nulla, quam rutrum conubia tortor primis.
|
||||
|
||||
- Non felis sem placerat aenean duis, ornare turpis nostra.
|
||||
|
||||
- Habitasse duis sociis sagittis cursus, ante dictumst commodo.
|
||||
|
||||
Duis maecenas massa habitasse inceptos imperdiet scelerisque at condimentum ultrices, nam dui leo enim taciti varius cras habitant pretium rhoncus, ut hac euismod nostra metus sagittis mi aenean. Quam eleifend aliquet litora eget a tempor, ultricies integer vestibulum non felis sodales, eros diam massa libero iaculis.
|
||||
|
||||
Nisl ligula ante magnis himenaeos pellentesque orci cras integer urna ut convallis, id phasellus libero est nunc ultrices eget blandit massa ac hac, morbi vulputate quisque tellus feugiat conubia luctus tincidunt curae fermentum. Venenatis dictumst tincidunt senectus vivamus duis dis sociis taciti porta primis, rhoncus ridiculus rutrum curae mattis ullamcorper ac sagittis nascetur curabitur erat, faucibus placerat vulputate eu at habitasse nulla nisl interdum. Varius turpis dignissim montes ac ante tristique quis parturient hendrerit faucibus, consequat auctor penatibus suspendisse rutrum erat nulla inceptos est justo, etiam mollis mauris facilisi cras sociosqu eu sapien sed.
|
||||
|
||||
Blandit aptent conubia mollis mauris habitasse suspendisse torquent aenean, ac primis auctor congue cursus mi posuere molestie, velit elementum per feugiat libero dictumst phasellus. Convallis mollis taciti condimentum praesent id porttitor ac dictumst at, sed in eu eleifend vehicula fermentum lectus litora venenatis, gravida hac molestie cum sociosqu mus viverra torquent. Congue est fusce habitasse ridiculus integer suscipit platea volutpat, inceptos varius elementum pellentesque malesuada interdum magnis. Hac lacus eget enim purus massa commodo nec lectus natoque fames arcu, mattis class quam ut neque dui cras quis diam orci sed velit, erat morbi eros suscipit sagittis laoreet vivamus torquent nulla turpis.
|
||||
|
||||
Ridiculus velit suscipit consequat auctor interdum magna gravida dictumst libero ut habitasse, sollicitudin vehicula suspendisse leo erat tristique at platea sagittis proin dignissim, id ornare scelerisque et urna maecenas congue tincidunt dictum malesuada. Dui vulputate accumsan scelerisque ridiculus dictum quisque et nam hac, tempus ultricies curabitur proin netus diam vivamus. Vestibulum ante ac auctor mi urna risus lacinia vulputate justo orci sociis dui semper, commodo morbi enim vivamus neque sem pellentesque velit donec hac metus odio. Tempor ultrices himenaeos massa sollicitudin mus conubia scelerisque cubilia, nascetur potenti mauris convallis et lectus gravida egestas sociis, erat eros ultricies aptent congue tortor ornare.
|
||||
|
||||
Pretium aliquet sodales aliquam tincidunt litora lectus, erat dui nibh diam mus, sed hendrerit condimentum senectus arcu. Arcu a nibh auctor dapibus eros turpis tempus commodo, libero hendrerit dictum interdum mus class sed scelerisque, sapien dictumst enim magna molestie habitant donec. Fringilla dui sed curabitur commodo varius est vel, viverra primis habitant sapien montes mattis dignissim, gravida cubilia laoreet tempus aliquet senectus. Sociosqu purus praesent porttitor curae sollicitudin accumsan feugiat maecenas donec quis lacus, suscipit taciti convallis odio morbi eros nibh bibendum nunc orci. Magna cras nullam aliquam metus nibh sagittis facilisi tortor nec, mus varius curae ridiculus fames congue interdum erat urna, neque odio lobortis mi mattis diam cubilia arcu.
|
||||
|
||||
Laoreet fusce nec class porttitor mus proin aenean, velit vestibulum feugiat porta egestas sapien posuere, conubia nisi tempus varius hendrerit tortor. Congue aliquam scelerisque neque vivamus habitasse semper mauris pellentesque accumsan posuere, suspendisse lectus gravida erat sagittis arcu praesent mus ornare. Habitasse nibh nam morbi mollis senectus erat risus, cum sollicitudin class platea congue mattis venenatis, luctus aenean parturient hendrerit malesuada ante. Mus auctor tincidunt consequat massa tortor nulla luctus habitasse vestibulum quis velit, laoreet sagittis cum facilisi in sem tellus leo vulputate vehicula bibendum orci, felis nisl blandit lacus convallis congue turpis magna facilisis condimentum.
|
||||
|
||||
Dictumst pellentesque urna donec sociis suscipit montes consequat, commodo quam habitasse senectus fringilla maecenas, inceptos magna tristique eu nullam nam. Maecenas orci nibh hac eu tristique ut penatibus ultrices ante, pellentesque cubilia pharetra dis facilisis aliquam praesent malesuada vivamus, commodo cras velit convallis molestie nec tellus augue. Etiam ut convallis risus id dapibus platea laoreet accumsan, habitant et aenean netus inceptos iaculis per, mauris curae at ligula odio ad eu. Mauris erat tempor interdum sapien commodo per nullam tortor, fusce facilisis vehicula egestas dui nulla conubia ut fames, fringilla et tincidunt penatibus facilisi at mollis.
|
||||
|
||||
Fermentum sociosqu litora primis sollicitudin fusce diam consequat vehicula per lobortis et, viverra sodales magna rutrum sed mollis faucibus molestie purus montes est, risus nostra congue venenatis lectus enim torquent eros dis dapibus. Dui suscipit scelerisque massa ligula euismod accumsan augue, magna vel lacus ante nullam senectus commodo, viverra cubilia eros eget penatibus tempor. Mattis mauris hac felis semper dui sociis faucibus mollis ornare pretium aliquam velit nisl, quis litora sem at vel duis rutrum imperdiet natoque viverra himenaeos tempor.
|
||||
|
||||
Integer eu tristique purus luctus vivamus porttitor vel nisl, tortor malesuada augue vulputate diam velit pellentesque sodales, duis phasellus vestibulum fermentum leo facilisi porta. Hac porttitor cum dapibus volutpat quisque odio taciti nulla senectus mollis curae, accumsan suscipit cubilia tempor ligula in venenatis justo leo erat, magna tincidunt nullam lacinia luctus malesuada non vivamus praesent pharetra. Non quam felis montes pretium volutpat suspendisse lacus, torquent magna dictumst orci libero porta, feugiat taciti cras ridiculus aenean rutrum. Tellus nostra tincidunt hac in ligula mi vulputate venenatis pellentesque urna dui, at luctus tristique quisque vel a dignissim scelerisque platea pretium, suspendisse ante phasellus porttitor quis aliquam malesuada etiam enim nullam.
|
||||
|
||||
Hendrerit taciti litora nec facilisis diam vehicula magnis potenti, parturient velit egestas nisl lobortis tincidunt rutrum cursus, fusce senectus mi massa primis mattis rhoncus. Accumsan est ac varius consequat vulputate, ligula cursus euismod sagittis inceptos scelerisque, lacus malesuada torquent dictumst. Volutpat morbi metus urna rhoncus nunc tempor molestie, congue curabitur quis interdum posuere. Mollis viverra velit tortor mus netus nunc molestie metus, sem massa himenaeos luctus feugiat taciti iaculis fames porttitor, leo arcu consequat gravida dapibus pulvinar elementum.
|
60
data/blog/how-to-customize-astrowind-to-your-brand.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
publishDate: 'Aug 10 2022'
|
||||
title: 'How to customize AstroWind template to suit your branding'
|
||||
description: 'Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat'
|
||||
image: '~/assets/images/colors.jpg'
|
||||
tags: [astro, tailwind css, theme]
|
||||
canonical: https://astrowind.vercel.app/how-to-customize-astrowind-to-your-brand # When posting content to multiple platforms at the same time (such as this website and Medium) and want to specify the ultimate authority. Remove it to automatically generate canonical
|
||||
---
|
||||
|
||||
## Congue justo vulputate nascetur convallis varius orci fringilla nulla pharetr
|
||||
|
||||
Lorem ipsum dolor sit amet consectetur adipiscing elit, augue malesuada natoque in ad erat aliquam facilisi, lacus rhoncus mattis nostra et a. Mauris malesuada rutrum dis libero egestas mus vulputate, fermentum ad morbi phasellus faucibus tellus leo urna, blandit ullamcorper diam imperdiet dictumst litora. Fringilla eros malesuada lobortis mi odio metus leo, blandit imperdiet augue fames aliquam ultricies tortor massa, duis magnis hendrerit id magna sociosqu. Aptent mi imperdiet id sapien suscipit ut netus turpis, lacinia ac porttitor potenti dui taciti at egestas, fermentum neque nascetur sodales tortor nunc congue.
|
||||
|
||||
Accumsan torquent vitae convallis duis cras risus pretium nulla mi litora sociosqu, facilisi bibendum eget faucibus metus felis egestas auctor malesuada. Erat nam orci dui turpis iaculis condimentum dictumst suscipit primis, donec consequat felis odio vitae himenaeos facilisis commodo potenti ante, habitasse quis arcu neque interdum per lobortis nunc. Ultricies lobortis ullamcorper sagittis et sollicitudin sociis sed dignissim posuere, nisi pharetra erat varius id aenean lacinia commodo morbi primis, ornare diam proin nunc volutpat nec dui egestas.
|
||||
|
||||
## Mauris velit laoreet vitae cursus augue
|
||||
|
||||
- Massa egestas consequat nisl id volutpat, varius neque aenean.
|
||||
|
||||
- Venenatis tincidunt eros pretium viverra lacinia convallis, turpis orci condimentum fusce.
|
||||
|
||||
- Pellentesque in aliquet nisi gravida netus, commodo aptent volutpat.
|
||||
|
||||
- Nisi rutrum eros euismod, parturient ullamcorper mattis a, dapibus vestibulum.
|
||||
|
||||
Senectus fermentum tristique egestas bibendum per dictumst purus pharetra cras dictum pulvinar, vitae nec eros montes dis quis nullam duis netus litora, feugiat cubilia mollis porttitor velit ligula metus ante risus eu.
|
||||
|
||||
Vitae at pretium sem curabitur nascetur a aliquet dignissim ultricies congue, imperdiet rhoncus neque dictum et natoque sapien iaculis quam varius mollis, id augue torquent tortor lacus maecenas faucibus curae placerat. Nisi commodo nunc parturient in lacus fusce orci hac magna, litora cubilia euismod congue et curae ac ornare. Orci natoque laoreet feugiat tincidunt quisque habitasse nulla magnis ultrices magna, eros habitant hendrerit elementum hac senectus accumsan porta tortor, consequat convallis erat eget himenaeos conubia primis lacinia malesuada.
|
||||
|
||||
Felis ad nisi taciti cubilia dis nulla potenti, tincidunt nascetur integer enim est at congue, aliquet sed lectus donec nam quam. Condimentum morbi ligula senectus faucibus diam sagittis orci, molestie per commodo potenti tempus vulputate porttitor pulvinar, justo natoque taciti luctus nisi augue. Ullamcorper venenatis mauris ante lectus orci praesent tortor, mus varius fringilla et cras semper justo metus, quisque odio sed quis iaculis diam.
|
||||
|
||||
Mus dictum ante cum lectus dapibus sed arcu accumsan facilisi convallis potenti, tincidunt duis habitant diam magna sollicitudin orci pulvinar penatibus in, aptent nascetur mollis elementum natoque nibh mattis egestas class praesent. Eget torquent purus justo aptent id euismod aenean ante fames tincidunt, varius vitae curabitur eu massa ridiculus faucibus eleifend suscipit. Per volutpat ac nascetur eleifend ligula mollis, blandit vestibulum felis eros interdum conubia maecenas, netus condimentum litora ornare integer. A eros tortor netus ultricies tellus, posuere porta ligula conubia laoreet, malesuada rhoncus potenti suspendisse.
|
||||
|
||||
Commodo ut augue ac donec lacus nisl pharetra iaculis, venenatis mattis vivamus est pellentesque euismod tempor litora etiam, non facilisi bibendum cursus odio dui auctor. Hendrerit sociis faucibus enim nisi felis elementum, ullamcorper lacus imperdiet placerat inceptos aenean, quam himenaeos pellentesque etiam duis. Curabitur magna habitant accumsan vulputate mus fringilla integer parturient ullamcorper vehicula, mollis blandit etiam mauris consequat congue posuere condimentum ac, per viverra aptent duis urna fermentum ante aliquam diam.
|
||||
|
||||
Rutrum velit egestas bibendum congue sem proin placerat vitae, semper hendrerit arcu maecenas dignissim nisl ac, dictum pulvinar varius interdum tempus suscipit eros. Ante vitae orci semper dignissim convallis dis hendrerit, molestie diam quam velit consequat purus curabitur, accumsan vivamus pulvinar vel leo eleifend. Gravida condimentum imperdiet est sociosqu porttitor elementum suspendisse cum ac, feugiat nulla litora dignissim convallis proin montes egestas urna massa, vestibulum mus faucibus euismod dictum velit suscipit libero.
|
||||
|
||||
Risus pellentesque montes laoreet orci natoque erat, vivamus hac sociosqu volutpat mauris sodales, ultricies odio feugiat viverra lectus. Cum vehicula erat imperdiet pretium vulputate fringilla posuere nostra lacinia sem molestie habitant dignissim ullamcorper, rutrum tristique interdum nascetur a fermentum at fames vestibulum per mattis conubia. Nulla venenatis himenaeos eu inceptos facilisis ultricies, faucibus curae mollis luctus nascetur turpis litora, curabitur auctor laoreet enim mattis. Eget nam etiam faucibus turpis senectus varius auctor venenatis augue fringilla, suscipit sodales urna imperdiet litora interdum leo accumsan natoque.
|
||||
|
||||
Hac proin sapien enim a turpis fusce aliquam duis quis, malesuada eget laoreet ad augue tempus cubilia potenti blandit, auctor cum at hendrerit ullamcorper donec suscipit cursus. Ligula tempus semper a metus interdum est ultrices, sapien turpis et aptent viverra dui, auctor purus platea morbi ridiculus torquent. Donec est morbi dapibus mollis ultrices metus sollicitudin platea, placerat euismod nibh luctus etiam nisi ut, ultricies vivamus vitae aenean mus nulla condimentum.
|
||||
|
||||
Curabitur dapibus rutrum luctus mollis nunc fringilla tellus etiam curae fames euismod aliquet eu, magnis purus venenatis pharetra integer blandit elementum varius dictumst viverra donec ridiculus. Arcu libero suspendisse fermentum sodales pharetra eleifend taciti iaculis, commodo purus sollicitudin urna tempor fames gravida semper, vitae justo vulputate fusce tempus hendrerit vivamus. Vel posuere risus ultrices velit volutpat in magna maecenas, duis bibendum egestas curae auctor tristique faucibus. Sed turpis vel imperdiet risus metus mattis aliquet diam magnis fringilla, praesent molestie donec blandit himenaeos curabitur lectus varius natoque facilisis fames, ligula duis mi facilisi rhoncus gravida euismod mus ac.
|
||||
|
||||
Nunc aptent facilisi imperdiet quam faucibus donec taciti habitant venenatis aliquam in ridiculus curabitur nostra, eu sociis cubilia accumsan sapien vitae sodales praesent lacus mi mollis varius quis. Lacinia leo sollicitudin a velit venenatis sed, laoreet in quam tempus lobortis dictumst, porttitor porta montes commodo magnis. Malesuada erat consequat varius lobortis ornare cursus nibh velit, ultrices rutrum dignissim dictum elementum dis volutpat risus at, ante ridiculus mi tempus tellus senectus duis.
|
||||
|
||||
Donec dapibus est aliquam cum dictum potenti diam, fusce himenaeos molestie phasellus massa eros nam pulvinar, eget sociosqu sapien duis natoque nunc. Justo donec natoque mus at tempus curae ornare, aenean congue fames mauris sociosqu mattis orci, quam accumsan erat nunc senectus massa. Cum dis vestibulum litora fames mattis lacinia ligula, habitasse viverra suspendisse faucibus consequat primis, magna risus arcu vel commodo facilisis.
|
||||
|
||||
Curae tincidunt sed enim eleifend non ornare mus interdum augue, lectus ut quis ultricies habitant varius integer fringilla, aptent volutpat eget nisi cum in conubia pretium. Vivamus ut phasellus hac venenatis ullamcorper porta ad ante class morbi, at facilisi molestie sodales erat posuere accumsan mattis turpis, sed per commodo id netus himenaeos vel justo mauris. Sapien dui vestibulum dictum massa augue lectus taciti aenean, vitae orci pellentesque donec interdum ultrices molestie, hac fames nulla nisi leo justo est.
|
||||
|
||||
Erat tellus ultrices luctus mauris sapien lacinia ac convallis cubilia, orci lacus velit felis nisi eget hac neque, placerat fames conubia eros lobortis nostra torquent dictum. Ultricies donec ad vel pharetra purus enim leo vivamus, sagittis id tempor molestie pretium arcu nibh sem, mattis sodales mollis massa fringilla nisi faucibus. Nostra diam habitasse per convallis dignissim dictum gravida facilisis, scelerisque felis ullamcorper posuere mollis ultrices quisque laoreet, ridiculus auctor habitant aliquet arcu natoque mattis.
|
||||
|
||||
Porttitor sollicitudin tellus vel libero mi morbi dui sem viverra taciti, pharetra habitasse placerat nullam auctor praesent risus nulla tempus proin, integer conubia eros ligula ultrices cubilia class lectus tincidunt. Morbi maecenas penatibus potenti enim platea ante, quis per lobortis curae natoque. Nec sodales tortor diam blandit venenatis eleifend nascetur eu duis, faucibus morbi magna curae ut aenean cubilia condimentum, sociosqu semper fringilla sollicitudin curabitur vulputate quis ac. Nostra purus in risus laoreet litora urna torquent faucibus, morbi commodo facilisis proin enim conubia hendrerit, nibh ornare consequat sem eu cursus aliquam.
|
||||
|
||||
Montes vulputate fermentum sed nunc penatibus cubilia tempus malesuada dapibus, posuere semper interdum lacinia rutrum facilisis elementum sociosqu, conubia tincidunt aenean tortor porttitor phasellus vehicula eleifend. Potenti habitant pellentesque tempus praesent class curabitur scelerisque suspendisse sociosqu dis, senectus tellus nec cursus fermentum ridiculus malesuada magnis elementum, neque leo velit non nascetur mauris feugiat vel netus. Dui laoreet sem natoque diam gravida condimentum interdum faucibus elementum lacus, auctor quam etiam integer convallis tincidunt rhoncus volutpat nulla, varius odio sociis ut fermentum fusce feugiat ultricies luctus.
|
||||
|
||||
Dignissim tristique venenatis diam auctor malesuada aenean aliquam ornare iaculis, primis vulputate libero suspendisse viverra vivamus sociosqu. Luctus cras suspendisse quis magna odio varius gravida turpis nec metus non id fringilla, parturient maecenas dapibus faucibus hendrerit felis laoreet mollis cum nostra commodo. Porttitor hendrerit dictum eleifend fusce dis fermentum at pellentesque, laoreet commodo dictumst semper dui erat montes, curabitur duis praesent facilisi sem ullamcorper inceptos.
|
||||
|
||||
Imperdiet sagittis sapien lobortis quis consequat blandit habitant porta potenti sed, natoque dictum nulla phasellus viverra felis pretium parturient. Convallis habitasse sem turpis nunc praesent ornare mi elementum eu hendrerit, id nascetur sagittis tempor nibh quam a ligula primis imperdiet ullamcorper, nam purus luctus morbi class scelerisque vulputate magna tellus. Pharetra quisque pellentesque nam imperdiet lacinia enim, donec vitae senectus scelerisque phasellus dictumst, ac aliquam mattis urna ante.
|
||||
|
||||
Habitant praesent pulvinar scelerisque per phasellus lobortis velit, magnis odio himenaeos primis curabitur senectus, nascetur ullamcorper convallis nunc placerat nisl. Porta tellus commodo praesent ullamcorper cursus senectus tempor vivamus, penatibus eu purus ultrices posuere mi sodales, urna quisque accumsan imperdiet convallis aptent nisl. Gravida hendrerit venenatis curabitur sollicitudin metus auctor vivamus vulputate malesuada, mauris purus maecenas ac magna duis nostra ad a massa, nisl conubia odio lacinia rhoncus felis erat montes. Nostra eros proin mi venenatis enim semper ad magnis netus, in vestibulum ornare ac fusce aliquet aptent non condimentum faucibus, tempor arcu potenti blandit magna consequat luctus nam.
|
188
data/blog/markdown-elements-demo-post.mdx
Normal file
|
@ -0,0 +1,188 @@
|
|||
---
|
||||
publishDate: 'Aug 02 2022'
|
||||
title: 'Markdown elements demo post'
|
||||
description: 'Lorem ipsum dolor sit amet'
|
||||
excerpt: 'Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat'
|
||||
image: '~/assets/images/astronaut.jpg'
|
||||
tags: [markdown, astro, blog]
|
||||
---
|
||||
|
||||
import Logo from '~/components/atoms/Logo.astro';
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
## <a name="Headings"></a>Headings
|
||||
|
||||
Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat commodo id sunt. Nostrud enim ad commodo incididunt cupidatat in ullamco ullamco Lorem cupidatat velit enim et Lorem. Ut laborum cillum laboris fugiat culpa sint irure do reprehenderit culpa occaecat. Exercitation esse mollit tempor magna aliqua in occaecat aliquip veniam reprehenderit nisi dolor in laboris dolore velit.
|
||||
|
||||
## Heading two
|
||||
|
||||
Aute officia nulla deserunt do deserunt cillum velit magna. Officia veniam culpa anim minim dolore labore pariatur voluptate id ad est duis quis velit dolor pariatur enim. Incididunt enim excepteur do veniam consequat culpa do voluptate dolor fugiat ad adipisicing sit. Labore officia est adipisicing dolore proident eiusmod exercitation deserunt ullamco anim do occaecat velit. Elit dolor consectetur proident sunt aliquip est do tempor quis aliqua culpa aute. Duis in tempor exercitation pariatur et adipisicing mollit irure tempor ut enim esse commodo laboris proident. Do excepteur laborum anim esse aliquip eu sit id Lorem incididunt elit irure ea nulla dolor et. Nulla amet fugiat qui minim deserunt enim eu cupidatat aute officia do velit ea reprehenderit.
|
||||
|
||||
### Heading three
|
||||
|
||||
Voluptate cupidatat cillum elit quis ipsum eu voluptate fugiat consectetur enim. Quis ut voluptate culpa ex anim aute consectetur dolore proident voluptate exercitation eiusmod. Esse in do anim magna minim culpa sint. Adipisicing ipsum consectetur proident ullamco magna sit amet aliqua aute fugiat laborum exercitation duis et.
|
||||
|
||||
#### Heading four
|
||||
|
||||
Commodo fugiat aliqua minim quis pariatur mollit id tempor. Non occaecat minim esse enim aliqua adipisicing nostrud duis consequat eu adipisicing qui. Minim aliquip sit excepteur ipsum consequat laborum pariatur excepteur. Veniam fugiat et amet ad elit anim laborum duis mollit occaecat et et ipsum et reprehenderit. Occaecat aliquip dolore adipisicing sint labore occaecat officia fugiat. Quis adipisicing exercitation exercitation eu amet est laboris sunt nostrud ipsum reprehenderit ullamco. Enim sint ut consectetur id anim aute voluptate exercitation mollit dolore magna magna est Lorem. Ut adipisicing adipisicing aliqua ullamco voluptate labore nisi tempor esse magna incididunt.
|
||||
|
||||
##### Heading five
|
||||
|
||||
Veniam enim esse amet veniam deserunt laboris amet enim consequat. Minim nostrud deserunt cillum consectetur commodo eu enim nostrud ullamco occaecat excepteur. Aliquip et ut est commodo enim dolor amet sint excepteur. Amet ad laboris laborum deserunt sint sunt aliqua commodo ex duis deserunt enim est ex labore ut. Duis incididunt velit adipisicing non incididunt adipisicing adipisicing. Ad irure duis nisi tempor eu dolor fugiat magna et consequat tempor eu ex dolore. Mollit esse nisi qui culpa ut nisi ex proident culpa cupidatat cillum culpa occaecat anim. Ut officia sit ea nisi ea excepteur nostrud ipsum et nulla.
|
||||
|
||||
###### Heading six
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## <a name="Paragraphs"></a>Paragraphs
|
||||
|
||||
Incididunt ex adipisicing ea ullamco consectetur in voluptate proident fugiat tempor deserunt reprehenderit ullamco id dolore laborum. Do laboris laboris minim incididunt qui consectetur exercitation adipisicing dolore et magna consequat magna anim sunt. Officia fugiat Lorem sunt pariatur incididunt Lorem reprehenderit proident irure. Dolore ipsum aliqua mollit ad officia fugiat sit eu aliquip cupidatat ipsum duis laborum laborum fugiat esse. Voluptate anim ex dolore deserunt ea ex eiusmod irure. Occaecat excepteur aliqua exercitation aliquip dolor esse eu eu.
|
||||
|
||||
Officia dolore laborum aute incididunt commodo nisi velit est est elit et dolore elit exercitation. Enim aliquip magna id ipsum aliquip consectetur ad nulla quis. Incididunt pariatur dolor consectetur cillum enim velit cupidatat laborum quis ex.
|
||||
|
||||
Officia irure in non voluptate adipisicing sit amet tempor duis dolore deserunt enim ut. Reprehenderit incididunt in ad anim et deserunt deserunt Lorem laborum quis. Enim aute anim labore proident laboris voluptate elit excepteur in. Ex labore nulla velit officia ullamco Lorem Lorem id do. Dolore ullamco ipsum magna dolor pariatur voluptate ipsum id occaecat ipsum. Dolore tempor quis duis commodo quis quis enim.
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## <a name="Blockquotes"></a>Blockquotes
|
||||
|
||||
Ad nisi laborum aute cupidatat magna deserunt eu id laboris id. Aliquip nulla cupidatat sint ex Lorem mollit laborum dolor amet est ut esse aute. Nostrud ex consequat id incididunt proident ipsum minim duis aliqua ut ex et ad quis. Laborum sint esse cillum anim nulla cillum consectetur aliqua sit. Nisi excepteur cillum labore amet excepteur commodo enim occaecat consequat ipsum proident exercitation duis id in.
|
||||
|
||||
> Ipsum et cupidatat mollit exercitation enim duis sunt irure aliqua reprehenderit mollit. Pariatur Lorem pariatur laboris do culpa do elit irure. Eiusmod amet nulla voluptate velit culpa et aliqua ad reprehenderit sit ut.
|
||||
|
||||
Labore ea magna Lorem consequat aliquip consectetur cillum duis dolore. Et veniam dolor qui incididunt minim amet laboris sit. Dolore ad esse commodo et dolore amet est velit ut nisi ea. Excepteur ea nulla commodo dolore anim dolore adipisicing eiusmod labore id enim esse quis mollit deserunt est. Minim ea culpa voluptate nostrud commodo proident in duis aliquip minim.
|
||||
|
||||
> Qui est sit et reprehenderit aute est esse enim aliqua id aliquip ea anim. Pariatur sint reprehenderit mollit velit voluptate enim consectetur sint enim. Quis exercitation proident elit non id qui culpa dolore esse aliquip consequat.
|
||||
|
||||
Ipsum excepteur cupidatat sunt minim ad eiusmod tempor sit.
|
||||
|
||||
> Deserunt excepteur adipisicing culpa pariatur cillum laboris ullamco nisi fugiat cillum officia. In cupidatat nulla aliquip tempor ad Lorem Lorem quis voluptate officia consectetur pariatur ex in est duis. Mollit id esse est elit exercitation voluptate nostrud nisi laborum magna dolore dolore tempor in est consectetur.
|
||||
|
||||
Adipisicing voluptate ipsum culpa voluptate id aute laboris labore esse fugiat veniam ullamco occaecat do ut. Tempor et esse reprehenderit veniam proident ipsum irure sit ullamco et labore ea excepteur nulla labore ut. Ex aute minim quis tempor in eu id id irure ea nostrud dolor esse.
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## <a name="Lists"></a>Lists
|
||||
|
||||
### Ordered List
|
||||
|
||||
1. Longan
|
||||
2. Lychee
|
||||
3. Excepteur ad cupidatat do elit laborum amet cillum reprehenderit consequat quis.
|
||||
Deserunt officia esse aliquip consectetur duis ut labore laborum commodo aliquip aliquip velit pariatur dolore.
|
||||
4. Marionberry
|
||||
5. Melon
|
||||
- Cantaloupe
|
||||
- Honeydew
|
||||
- Watermelon
|
||||
6. Miracle fruit
|
||||
7. Mulberry
|
||||
|
||||
### Unordered List
|
||||
|
||||
- Olive
|
||||
- Orange
|
||||
- Blood orange
|
||||
- Clementine
|
||||
- Papaya
|
||||
- Ut aute ipsum occaecat nisi culpa Lorem id occaecat cupidatat id id magna laboris ad duis. Fugiat cillum dolore veniam nostrud proident sint consectetur eiusmod irure adipisicing.
|
||||
- Passionfruit
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## <a name="Horizontal"></a>Horizontal rule
|
||||
|
||||
In dolore velit aliquip labore mollit minim tempor veniam eu veniam ad in sint aliquip mollit mollit. Ex occaecat non deserunt elit laborum sunt tempor sint consequat culpa culpa qui sit. Irure ad commodo eu voluptate mollit cillum cupidatat veniam proident amet minim reprehenderit.
|
||||
|
||||
---
|
||||
|
||||
In laboris eiusmod reprehenderit aliquip sit proident occaecat. Non sit labore anim elit veniam Lorem minim commodo eiusmod irure do minim nisi. Dolor amet cillum excepteur consequat sint non sint.
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## <a name="Table"></a>Table
|
||||
|
||||
Duis sunt ut pariatur reprehenderit mollit mollit magna dolore in pariatur nulla commodo sit dolor ad fugiat. Laboris amet ea occaecat duis eu enim exercitation deserunt ea laborum occaecat reprehenderit. Et incididunt dolor commodo consequat mollit nisi proident non pariatur in et incididunt id. Eu ut et Lorem ea ex magna minim ipsum ipsum do.
|
||||
|
||||
| Table Heading 1 | Table Heading 2 | Center align | Right align | Table Heading 5 |
|
||||
| :-------------- | :-------------- | :----------: | ----------: | :-------------- |
|
||||
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
|
||||
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
|
||||
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
|
||||
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
|
||||
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
|
||||
|
||||
Minim id consequat adipisicing cupidatat laborum culpa veniam non consectetur et duis pariatur reprehenderit eu ex consectetur. Sunt nisi qui eiusmod ut cillum laborum Lorem officia aliquip laboris ullamco nostrud laboris non irure laboris. Cillum dolore labore Lorem deserunt mollit voluptate esse incididunt ex dolor.
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## <a name="Code"></a>Code
|
||||
|
||||
### Inline code
|
||||
|
||||
Ad amet irure est magna id mollit Lorem in do duis enim. Excepteur velit nisi magna ea pariatur pariatur ullamco fugiat deserunt sint non sint. Duis duis est `code in text` velit velit aute culpa ex quis pariatur pariatur laborum aute pariatur duis tempor sunt ad. Irure magna voluptate dolore consectetur consectetur irure esse. Anim magna `<strong>in culpa qui officia</strong>` dolor eiusmod esse amet aute cupidatat aliqua do id voluptate cupidatat reprehenderit amet labore deserunt.
|
||||
|
||||
### Highlighted
|
||||
|
||||
Et fugiat ad nisi amet magna labore do cillum fugiat occaecat cillum Lorem proident. In sint dolor ullamco ad do adipisicing amet id excepteur Lorem aliquip sit irure veniam laborum duis cillum. Aliqua occaecat minim cillum deserunt magna sunt laboris do do irure ea nostrud consequat ut voluptate ex.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", handler)
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
||||
```
|
||||
|
||||
Ex amet id ex aliquip id do laborum excepteur exercitation elit sint commodo occaecat nostrud est. Nostrud pariatur esse veniam laborum non sint magna sit laboris minim in id. Aliqua pariatur pariatur excepteur adipisicing irure culpa consequat commodo et ex id ad.
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## <a name="Inline"></a>Inline elements
|
||||
|
||||
Sint ea anim ipsum ad commodo cupidatat do **exercitation** incididunt et minim ad labore sunt. Minim deserunt labore laboris velit nulla incididunt ipsum nulla. Ullamco ad laborum ea qui et anim in laboris exercitation tempor sit officia laborum reprehenderit culpa velit quis. **Consequat commodo** reprehenderit duis [irure](#!) esse esse exercitation minim enim Lorem dolore duis irure. Nisi Lorem reprehenderit ea amet excepteur dolor excepteur magna labore proident voluptate ipsum. Reprehenderit ex esse deserunt aliqua ea officia mollit Lorem nulla magna enim. Et ad ipsum labore enim ipsum **cupidatat consequat**. Commodo non ea cupidatat magna deserunt dolore ipsum velit nulla elit veniam nulla eiusmod proident officia.
|
||||
|
||||

|
||||
|
||||
_Proident sit veniam in est proident officia adipisicing_ ea tempor cillum non cillum velit deserunt. Voluptate laborum incididunt sit consectetur Lorem irure incididunt voluptate nostrud. Commodo ut eiusmod tempor cupidatat esse enim minim ex anim consequat. Mollit sint culpa qui laboris quis consectetur ad sint esse. Amet anim anim minim ullamco et duis non irure. Sit tempor adipisicing ea laboris `culpa ex duis sint` anim aute reprehenderit id eu ea. Aute [excepteur proident](#!) Lorem minim adipisicing nostrud mollit ad ut voluptate do nulla esse occaecat aliqua sint anim.
|
||||
|
||||

|
||||
|
||||
Incididunt in culpa cupidatat mollit cillum qui proident sit. In cillum aliquip incididunt voluptate magna amet cupidatat cillum pariatur sint aliqua est _enim **anim** voluptate_. Magna aliquip proident incididunt id duis pariatur eiusmod incididunt commodo culpa dolore sit. Culpa do nostrud elit ad exercitation anim pariatur non minim nisi **adipisicing sunt _officia_**. Do deserunt magna mollit Lorem commodo ipsum do cupidatat mollit enim ut elit veniam ea voluptate.
|
||||
|
||||
Reprehenderit non eu quis in ad elit esse qui aute id [incididunt](#!) dolore cillum. Esse laboris consequat dolor anim exercitation tempor aliqua deserunt velit magna laboris. Culpa culpa minim duis amet mollit do quis amet commodo nulla irure.
|
||||
|
||||
[[Top]](#top)
|
||||
|
||||
## MDX
|
||||
|
||||
```js
|
||||
---
|
||||
publishDate: 'Aug 02 2022'
|
||||
title: 'Markdown elements demo post'
|
||||
---
|
||||
import Logo from "~/components/atoms/Logo.astro";
|
||||
|
||||
## MDX
|
||||
|
||||
<Logo />
|
||||
```
|
||||
|
||||
<div style="background:#eee;padding: 10px 5px">
|
||||
<Logo />
|
||||
</div>
|
||||
|
||||
[[Top]](#top)
|
59
data/blog/useful-resources-to-create-websites.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
publishDate: 'Aug 09 2022'
|
||||
title: 'Useful tools and resources to create a professional website'
|
||||
description: 'Nibh senectus lacinia volutpat nostra taciti ac posuere, dictum ultricies dictumst luctus in vehicula, mus molestie venenatis penatibus ridiculus elementum. Phasellus sollicitudin dignissim parturient.'
|
||||
image: '~/assets/images/tools.jpg'
|
||||
tags: [front-end, tools, resources]
|
||||
---
|
||||
|
||||
## Magna nunc senectus torquent per fusce sapien ligula tempus cra
|
||||
|
||||
Lorem ipsum dolor sit amet consectetur adipiscing, elit fusce imperdiet gravida velit massa, ligula aenean suscipit sociis lacinia. Sapien scelerisque rutrum sem accumsan orci imperdiet aliquam inceptos aliquet tempus ornare, netus nostra nam nunc platea pulvinar urna et suscipit pellentesque, aenean congue sociis non tellus quis proin etiam venenatis pretium. Nibh senectus lacinia volutpat nostra taciti ac posuere, dictum ultricies dictumst luctus in vehicula, mus molestie venenatis penatibus ridiculus elementum. Phasellus sollicitudin dignissim parturient tempor cubilia erat massa eleifend dapibus, condimentum cras tortor eu sem dictumst non. Faucibus neque est malesuada nostra luctus maecenas at condimentum, arcu eros vulputate curabitur blandit mollis volutpat, lectus leo dictumst duis semper tempor hendrerit. Egestas scelerisque fusce torquent cubilia consequat conubia lacus et mollis, condimentum taciti elementum sapien risus vulputate est.
|
||||
|
||||
Tristique eleifend enim praesent mollis sem leo, molestie dictum penatibus sodales consequat ligula nulla, platea feugiat aptent sapien turpis. Mollis mus ac taciti maecenas pretium hendrerit proin accumsan, mattis dictumst netus nunc facilisi morbi cursus euismod quis, a commodo nulla integer varius enim vehicula. Consequat mi risus vulputate ullamcorper sociosqu pretium molestie cursus, parturient viverra non tempor tellus convallis vitae eleifend mus, bibendum pellentesque imperdiet vivamus nunc phasellus iaculis. Volutpat est ac dictumst eleifend maecenas torquent quam hac, mollis aliquam mattis euismod ornare risus fringilla proin nisi, sem fermentum primis ultrices varius etiam id. Posuere nunc mus curabitur condimentum lobortis euismod donec tincidunt ridiculus, tristique senectus cum taciti quam blandit leo malesuada, sociis nullam cras litora sem laoreet sed nec.
|
||||
|
||||
## Magna lacus tortor luctus platea co
|
||||
|
||||
- Luctus molestie taciti aliquam dictumst imperdiet, donec torquent nisi.
|
||||
|
||||
- Montes cursus habitant risus platea senectus, lectus sagittis mi.
|
||||
|
||||
- Eleifend facilisi quam ultricies, accumsan aliquet euismod velit, sem tortor.
|
||||
|
||||
- Senectus nisl potenti congue sociosqu at, porttitor habitant vivamus.
|
||||
|
||||
Nostra dictum porta consequat quisque diam nisl iaculis velit varius, placerat curabitur risus commodo condimentum morbi eros dictumst phasellus, tempor duis libero ultrices est rhoncus mattis nam. Quisque lectus massa lobortis nulla enim, praesent eu ut elementum. Felis placerat nibh donec erat platea rutrum taciti cursus, elementum metus semper feugiat risus tellus nulla, aliquam hendrerit faucibus inceptos commodo justo porta.
|
||||
|
||||
Cursus imperdiet montes natoque potenti suscipit facilisi porta mollis posuere consequat, aliquam turpis tortor libero viverra rhoncus accumsan inceptos blandit convallis diam, penatibus ut pretium in duis leo auctor proin quisque. Sollicitudin inceptos quam molestie sociis habitasse class sapien vivamus facilisis, consequat ante vehicula velit tempor cum rutrum magnis, eget semper quisque turpis pretium praesent per faucibus. Ullamcorper blandit taciti primis sed pharetra inceptos duis, eu nisi ac fringilla tellus accumsan iaculis, morbi integer at purus hac est. Elementum hac lacus per in posuere erat ad, egestas dapibus malesuada suscipit nunc interdum, mi risus auctor pretium lectus massa. Condimentum nullam molestie tincidunt sodales luctus parturient est et congue hendrerit vel vulputate iaculis, curabitur sollicitudin quisque magna nostra nisl nam massa viverra donec neque class.
|
||||
|
||||
Euismod tempus potenti interdum fusce placerat habitant, taciti turpis faucibus curabitur tempor felis porta, sed aenean mi arcu magnis. Pellentesque tincidunt aptent eget nisi convallis lobortis sapien, habitasse sollicitudin proin vehicula ridiculus duis congue, himenaeos lectus vitae nulla taciti ante. Enim commodo non taciti ultricies donec iaculis aliquet interdum, dictumst a pulvinar lacus cursus fames praesent cras ad, rutrum nostra dis accumsan primis euismod sagittis. Eu habitant euismod mattis at congue fusce ad commodo litora himenaeos aenean, porta lobortis suscipit pulvinar magna facilisi nullam ante non senectus, urna volutpat sodales vitae varius lectus tincidunt montes rutrum vulputate. Enim cum habitant morbi maecenas nisl imperdiet a egestas velit, gravida laoreet hendrerit rutrum molestie fames sapien euismod turpis metus, faucibus class sed primis leo nam malesuada fermentum.
|
||||
|
||||
Semper etiam tellus a risus lobortis dictumst sem massa eros, eget curae gravida accumsan hac parturient nulla fringilla convallis, condimentum torquent placerat mauris conubia augue mattis leo. Dictum tincidunt quis risus volutpat netus mi suscipit parturient suspendisse vestibulum, ad lacus dictumst luctus nec fusce ultricies vivamus. Dui sociis nulla suscipit gravida mi arcu netus, vitae mus donec dapibus nascetur id ante urna, egestas viverra auctor sodales litora enim rutrum, sapien molestie imperdiet ut massa elementum. Aptent ante risus erat malesuada nec porta, ligula nascetur dictum nunc turpis natoque, tristique conubia netus arcu a.
|
||||
|
||||
Nam scelerisque ridiculus suspendisse viverra conubia et fermentum nascetur turpis quisque, vestibulum cubilia curae per feugiat lectus rhoncus suscipit neque. Urna habitasse mus hac fringilla rutrum sodales, nullam aliquam porttitor quis vehicula arcu class, in felis placerat mattis vestibulum habitant, mauris eros dapibus penatibus viverra. Senectus tristique molestie scelerisque quisque mus augue facilisi massa, ac viverra dapibus vehicula nostra vel nam, posuere montes parturient auctor eu ultrices natoque. Quam fringilla volutpat morbi in per aliquet laoreet a maecenas, lacus velit mauris purus ultricies sociosqu pulvinar netus sodales, convallis placerat turpis tellus nullam libero leo aptent. Praesent lacus ultricies per ligula taciti aenean conubia parturient, feugiat sodales viverra urna cubilia etiam nibh curabitur congue, tristique nisl at elementum dis natoque commodo.
|
||||
|
||||
Sagittis erat velit integer cursus congue viverra, conubia himenaeos egestas ultricies praesent, hac litora mattis non venenatis. Duis libero morbi curae potenti litora vitae sed etiam consequat magna ultricies, magnis fermentum vehicula feugiat tortor ad quis orci rhoncus per porta, ante mi gravida dis nostra tempor lobortis aenean convallis molestie. Ligula fusce blandit ac accumsan magnis rutrum nostra velit maecenas, netus lobortis himenaeos purus justo sapien posuere libero, cum etiam urna mi ultrices est sociis tortor. Neque inceptos quisque vestibulum tempor phasellus id himenaeos magna suspendisse a in nunc cursus, morbi dignissim ornare non auctor massa iaculis mus nec elementum ultricies maecenas. Scelerisque maecenas ultrices integer gravida dis cursus, sed at semper libero iaculis varius, justo augue nec tincidunt suspendisse.
|
||||
|
||||
Rutrum augue natoque felis non vestibulum nam duis, quam praesent taciti himenaeos class vel dis rhoncus, dapibus pulvinar etiam ridiculus curae nibh blandit, scelerisque cursus nostra pretium suspendisse vehicula. Etiam sem metus eleifend suscipit felis suspendisse ut, velit fames habitant semper placerat fusce cras, nunc venenatis platea aenean euismod libero. In eu eget pellentesque libero egestas suspendisse quis tristique torquent nulla, magnis dis malesuada purus quam platea aliquet tortor odio. Accumsan nostra augue lobortis elementum justo sociosqu posuere aptent est, nisl metus conubia tellus sollicitudin lacus inceptos. Morbi mauris aenean malesuada arcu fusce libero venenatis commodo iaculis litora dis, erat parturient class sed facilisi mus a nec dictum.
|
||||
|
||||
Senectus platea dapibus volutpat dictum pharetra cursus netus cras, arcu sociis ornare potenti porttitor tempus sollicitudin, ullamcorper duis nam convallis sapien pretium conubia. Mi metus vivamus cum id semper fringilla senectus scelerisque pretium placerat sociis rhoncus pulvinar porttitor accumsan, curae ligula fermentum mus hendrerit ridiculus condimentum per suscipit rutrum sociosqu odio pellentesque suspendisse. Dui massa nulla suscipit duis metus mollis pellentesque, scelerisque posuere interdum ligula cum dignissim sed, placerat ante ultrices mi netus augue. Eu porttitor malesuada diam morbi torquent egestas magnis tempus metus imperdiet nisl, ad sociis lectus neque mauris gravida habitant primis lobortis. Phasellus mattis nulla fames parturient pharetra pretium egestas, diam rhoncus placerat lectus maecenas dictumst sed cum, justo non ac volutpat morbi enim.
|
||||
|
||||
Justo fringilla morbi netus habitasse varius primis eu magna, tristique accumsan mus enim lectus cubilia convallis auctor, nunc imperdiet erat mollis rutrum vel turpis. Justo purus laoreet eros turpis interdum et ridiculus torquent integer nunc, himenaeos eu tellus proin scelerisque tincidunt congue posuere ultricies vestibulum auctor, aliquet semper varius placerat imperdiet non nisl cubilia fermentum. Feugiat nisl himenaeos cum metus mi est ac, euismod elementum velit tempus dictum mauris, bibendum faucibus cubilia phasellus nulla ornare. Etiam justo venenatis varius laoreet sociis montes dignissim, elementum ligula malesuada euismod praesent magnis auctor, eleifend class egestas a vestibulum blandit. Scelerisque potenti facilisis torquent mollis nisi felis et sed, aptent tortor platea non quisque nec accumsan inceptos, velit molestie nunc enim cubilia egestas per.
|
||||
|
||||
Ultrices morbi et potenti eros aenean condimentum magnis est felis porta, dictumst taciti inceptos etiam ultricies cubilia hac torquent tempor vulputate, sodales erat semper vestibulum dignissim sociis viverra suscipit sagittis. Justo non auctor penatibus iaculis sed in volutpat pretium feugiat lectus rutrum, curabitur sociosqu sapien semper a laoreet augue primis fringilla dui. Fringilla iaculis blandit feugiat euismod congue morbi erat eros, mi dis egestas facilisi volutpat risus cras porta, orci vivamus turpis conubia est commodo torquent. Lectus euismod maecenas potenti in ac natoque sed ullamcorper ridiculus, diam fringilla condimentum eget convallis hendrerit varius pellentesque. Feugiat cras nullam tristique leo nisl dignissim lacinia aenean vivamus potenti consequat, vulputate curabitur sed risus mus suspendisse litora sollicitudin tempor.
|
||||
|
||||
Egestas hac arcu dapibus placerat proin aptent a pellentesque posuere, in condimentum fames facilisi maecenas semper nisl mus, sodales donec elementum praesent enim ac dictum ridiculus. Justo in nibh luctus vitae etiam nisl ac quisque fringilla, habitasse sociosqu curae inceptos semper ut mi hac, congue volutpat himenaeos sed augue morbi tellus nec. Congue libero posuere varius eleifend tristique nascetur integer ullamcorper, est leo vitae mi erat enim augue urna magnis, elementum ultricies pulvinar blandit arcu malesuada duis. Cubilia nulla vel et integer sed pellentesque gravida felis pulvinar mollis ultricies mi, montes suspendisse vestibulum aliquet dui in magna nunc ridiculus aliquam elementum. Justo erat montes enim felis eu sed vivamus faucibus imperdiet ac luctus vulputate, cursus accumsan blandit et mus sodales conubia cubilia phasellus leo.
|
||||
|
||||
Velit in felis penatibus semper laoreet libero tristique condimentum sem montes suscipit, morbi habitant gravida tellus quisque neque torquent lobortis interdum. Ridiculus sollicitudin suscipit semper quam eleifend at, neque tincidunt magnis penatibus dui orci, praesent vulputate himenaeos feugiat vel. Habitasse senectus a sodales dapibus nulla auctor sagittis nullam molestie, imperdiet volutpat quam odio facilisis nostra magnis dictumst, sociis cum erat facilisi dignissim urna lacus magna. Primis porttitor nullam quis vestibulum mi dictumst magna dapibus taciti magnis inceptos fames, purus etiam auctor metus bibendum felis accumsan id aliquet suscipit imperdiet. Pellentesque sem velit nulla consequat vehicula cubilia curabitur, platea curae natoque tristique nullam litora, nascetur imperdiet habitant tincidunt suspendisse sociis.
|
||||
|
||||
Platea cum auctor eget consequat elementum lacinia ad aliquet orci, imperdiet nibh penatibus ac dictum rutrum mollis ante cursus, volutpat scelerisque velit ornare in vivamus pharetra blandit. Cum mattis interdum in diam purus sapien lacinia gravida, semper montes vestibulum rhoncus auctor morbi dictum. Mus semper erat mollis taciti sapien ultrices accumsan ante magna eros at commodo, malesuada diam nullam massa curabitur lobortis felis interdum nisi duis pellentesque. Accumsan faucibus tristique augue enim hac ante feugiat, porttitor phasellus condimentum nulla maecenas dignissim at platea, facilisis nam donec primis habitasse ac. Nec convallis ridiculus potenti primis faucibus erat eget metus mollis, luctus ac fusce condimentum orci suscipit volutpat malesuada mi, velit feugiat pharetra sem turpis est accumsan porta, ligula torquent lacus tristique a senectus tortor dignissim.
|
||||
|
||||
Pharetra eleifend vivamus potenti congue proin himenaeos, fusce mi venenatis natoque montes, suscipit commodo porta magnis mattis. Et lobortis mollis libero quis himenaeos felis dis porta, donec iaculis mattis cursus accumsan pulvinar mus etiam, habitasse leo taciti vitae suscipit suspendisse bibendum. Sodales at ante dictumst nostra est risus senectus semper morbi facilisis neque tempus, venenatis penatibus fusce mattis phasellus velit diam iaculis hac tortor class, orci ridiculus varius dis odio cras rutrum porttitor facilisi massa parturient. Augue facilisi nam proin at elementum massa, tellus vestibulum mattis tortor porta, cubilia sodales orci congue vel. Rhoncus nec quam iaculis sapien risus suspendisse dictum tincidunt, vivamus lobortis blandit metus ullamcorper torquent.
|
||||
|
||||
Ante fermentum hac tincidunt nam sodales vestibulum pellentesque ut nulla habitasse, ornare diam facilisis aptent facilisi penatibus arcu congue lacus, lectus fringilla per primis dapibus eu imperdiet erat dictumst. Pulvinar eu ad mauris nulla ac sed nisl ullamcorper natoque etiam fames, platea aliquam dis netus odio dignissim tincidunt quam blandit laoreet, at mollis ridiculus molestie lacus metus nullam suspendisse nibh duis. Suspendisse congue vestibulum fringilla ridiculus tristique sagittis sociosqu integer, volutpat lacinia pulvinar felis aliquam pharetra faucibus dictumst ad, fusce dignissim cursus mauris eget nostra lectus. Lacinia egestas iaculis scelerisque odio gravida ullamcorper, at arcu ligula ornare parturient phasellus laoreet, augue convallis platea tortor aenean.
|
||||
|
||||
Interdum fames lobortis sollicitudin aliquet mus aptent netus, penatibus consequat pulvinar velit enim curae accumsan, maecenas litora mi rutrum sagittis tincidunt. Lacinia malesuada id netus suscipit sapien sociosqu orci habitasse turpis, feugiat donec placerat sed quam hendrerit pellentesque. Erat accumsan ligula id sapien turpis mus nulla lobortis consequat nec, urna habitasse ultrices aliquet vulputate est suspendisse gravida senectus odio, vehicula fusce proin in sed tempor vitae convallis molestie. Nascetur semper feugiat velit hendrerit lacinia nunc, risus quis congue nullam himenaeos commodo porttitor, natoque facilisi ad maecenas faucibus. Dictum id sodales interdum accumsan habitant natoque class parturient mi venenatis aenean, est nam tortor donec lobortis non vehicula magnis lacinia. Feugiat vitae morbi litora vehicula in a, nam ad ultrices auctor sollicitudin, ullamcorper fringilla hendrerit placerat faucibus.
|
||||
|
||||
Nulla nisi ac placerat duis semper mus cursus interdum netus vestibulum, tortor praesent proin nec rhoncus magnis commodo blandit himenaeos purus, volutpat id montes scelerisque suspendisse risus nisl erat dui. Senectus et habitant dis nulla velit faucibus venenatis sapien, dapibus etiam metus eget magnis feugiat tristique. Augue montes elementum pulvinar mollis pellentesque diam cursus tristique vel cubilia erat mus, congue curae sagittis dui quis fusce tortor consequat taciti natoque. Praesent montes erat feugiat sed euismod condimentum potenti malesuada nec, mi vitae suspendisse aptent senectus eleifend faucibus pulvinar scelerisque, augue ornare accumsan pretium magna eu iaculis metus. Suscipit accumsan massa vitae platea ad duis rhoncus fermentum vulputate, interdum pretium metus per aptent enim in facilisis eros, sollicitudin consequat iaculis erat dictumst quisque leo sociis.
|
||||
|
||||
Tempor etiam potenti auctor est ut habitant ac nisl ultrices pulvinar, sem primis tempus lacus aliquam consequat fringilla tristique. Consequat cum rhoncus massa sociis blandit rutrum nisi quam cras vitae fusce, sociosqu erat penatibus convallis fames accumsan eros himenaeos pulvinar sagittis, habitasse primis integer odio nascetur in montes faucibus semper potenti. Diam aliquam fringilla risus phasellus habitasse aenean eu erat, netus nulla pellentesque ut morbi torquent pharetra semper, sed etiam primis in conubia hendrerit velit. Ornare magna dictum purus metus sociosqu pulvinar sed, quam faucibus posuere pretium senectus interdum. Ornare sodales in litora nascetur sociosqu senectus auctor, cras arcu fusce ac inceptos integer tempor aliquam, tristique imperdiet metus hendrerit erat eleifend.
|
|
@ -1 +0,0 @@
|
|||
hello world
|
BIN
lighthouse-score.png
Normal file
After Width: | Height: | Size: 70 KiB |
7
netlify.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[build]
|
||||
publish = "dist"
|
||||
command = "npm run build"
|
||||
[[headers]]
|
||||
for = "/assets/*"
|
||||
[headers.values]
|
||||
Cache-Control = "public, max-age=31536000, immutable"
|
10590
package-lock.json
generated
44
package.json
|
@ -1,19 +1,47 @@
|
|||
{
|
||||
"name": "@forgejo/website",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"name": "@onwidget/astrowind",
|
||||
"description": "A template to make your website using Astro + Tailwind CSS.",
|
||||
"version": "0.8.4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro check && astro build",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
"astro": "astro",
|
||||
"format": "prettier -w .",
|
||||
"lint:eslint": "eslint . --ext .js,.ts,.astro",
|
||||
"subfont": "subfont -ir --no-fallbacks --silent --root dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"devDependencies": {
|
||||
"@astrojs/image": "^0.11.6",
|
||||
"@astrojs/mdx": "^0.11.6",
|
||||
"@astrojs/partytown": "^1.0.1",
|
||||
"@astrojs/rss": "^1.0.3",
|
||||
"@astrojs/sitemap": "^1.0.0",
|
||||
"@astrojs/tailwind": "^2.1.2",
|
||||
"@astrolib/analytics": "^0.2.4",
|
||||
"@astrolib/seo": "^0.2.1",
|
||||
"@fontsource/inter": "^4.5.14",
|
||||
"@tailwindcss/typography": "^0.5.8",
|
||||
"astro": "^1.6.5",
|
||||
"tailwindcss": "^3.2.3"
|
||||
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
||||
"@typescript-eslint/parser": "^5.44.0",
|
||||
"astro": "^1.6.10",
|
||||
"astro-icon": "^0.8.0",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-plugin-astro": "^0.21.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||
"limax": "^2.1.0",
|
||||
"mdast-util-to-string": "^3.1.0",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-astro": "^0.7.0",
|
||||
"reading-time": "^1.5.0",
|
||||
"sharp": "^0.31.2",
|
||||
"subfont": "^6.12.2",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"typescript": "^4.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || >=16.0.0"
|
||||
}
|
||||
}
|
||||
|
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
2
public/robots.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
User-agent: *
|
||||
Disallow:
|
11
sandbox.config.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"infiniteLoopProtection": true,
|
||||
"hardReloadOnChange": false,
|
||||
"view": "browser",
|
||||
"template": "node",
|
||||
"container": {
|
||||
"port": 3000,
|
||||
"startScript": "start",
|
||||
"node": "14"
|
||||
}
|
||||
}
|
BIN
screenshot.jpg
Normal file
After Width: | Height: | Size: 297 KiB |
BIN
src/assets/images/astronaut.jpg
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
src/assets/images/colors.jpg
Normal file
After Width: | Height: | Size: 93 KiB |
BIN
src/assets/images/default.png
Normal file
After Width: | Height: | Size: 285 KiB |
BIN
src/assets/images/hero.jpg
Normal file
After Width: | Height: | Size: 599 KiB |
BIN
src/assets/images/old.jpg
Normal file
After Width: | Height: | Size: 620 KiB |
BIN
src/assets/images/steps.jpg
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
src/assets/images/tools.jpg
Normal file
After Width: | Height: | Size: 163 KiB |
37
src/assets/styles/base.css
Normal file
|
@ -0,0 +1,37 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply inline-flex items-center justify-center rounded-md shadow-md border-gray-400 border bg-transparent font-medium text-center text-base text-gray-700 leading-snug transition py-3 px-6 md:px-8 ease-in duration-200 focus:ring-blue-500 focus:ring-offset-blue-200 focus:ring-2 focus:ring-offset-2 hover:bg-gray-100 hover:border-gray-600 dark:text-slate-300 dark:border-slate-500 dark:hover:bg-slate-800 dark:hover:border-slate-800;
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
@apply border-none shadow-none text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply font-semibold bg-primary-600 text-white border-primary-600 hover:bg-primary-800 hover:border-primary-800 hover:text-white dark:text-white dark:bg-primary-700 dark:border-primary-700 dark:hover:border-primary-900 dark:hover:bg-primary-900;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
[astro-icon].icon-light > * {
|
||||
stroke-width: 1.2;
|
||||
}
|
||||
|
||||
[data-aw-toggle-menu] path {
|
||||
@apply transition;
|
||||
}
|
||||
[data-aw-toggle-menu].expanded g > path:first-child {
|
||||
@apply -rotate-45 translate-y-[15px] translate-x-[-3px];
|
||||
}
|
||||
|
||||
[data-aw-toggle-menu].expanded g > path:last-child {
|
||||
@apply rotate-45 translate-y-[-8px] translate-x-[14px];
|
||||
}
|
7
src/components/atoms/ExtraMetaTags.astro
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
import { getRelativeLink } from '~/utils/permalinks';
|
||||
---
|
||||
|
||||
<link rel="shortcut icon" href={getRelativeLink('/favicon.ico')} />
|
||||
<link rel="icon" type="image/svg+xml" href={getRelativeLink('/favicon.svg')} />
|
||||
<link rel="mask-icon" href={getRelativeLink('/favicon.svg')} color="#8D46E7" />
|
5
src/components/atoms/Fonts.astro
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
import '@fontsource/inter/variable.css';
|
||||
---
|
||||
|
||||
<!-- Or Google Fonts -->
|
6
src/components/atoms/Logo.astro
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
---
|
||||
|
||||
<span class="self-center ml-2 text-2xl md:text-xl font-bold text-gray-900 whitespace-nowrap dark:text-white">
|
||||
🚀 AstroWind</span
|
||||
>
|
35
src/components/atoms/Pagination.astro
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
import { getRelativeLink } from '~/utils/permalinks';
|
||||
const { prevUrl, nextUrl, prevText = 'Newer posts', nextText = 'Older posts' } = Astro.props;
|
||||
---
|
||||
|
||||
{
|
||||
(prevUrl || nextUrl) && (
|
||||
<div class="container flex">
|
||||
<div class="flex flex-row mx-auto container justify-between">
|
||||
<a
|
||||
href={getRelativeLink(prevUrl)}
|
||||
class={`btn btn-ghost px-3 mr-2
|
||||
${!prevUrl ? 'invisible' : ''}`}
|
||||
>
|
||||
<div class="flex flex-row align-middle">
|
||||
<Icon name="tabler:arrow-left" class="w-6 h-6" />
|
||||
<p class="ml-2">{prevText}</p>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
href={getRelativeLink(nextUrl)}
|
||||
class={`btn btn-ghost px-3 ${
|
||||
!nextUrl ? 'invisible' : ''
|
||||
}`}
|
||||
>
|
||||
<div class="flex flex-row align-middle">
|
||||
<span class="mr-2">{nextText}</span>
|
||||
<Icon name="tabler:arrow-right" class="w-6 h-6" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
23
src/components/atoms/SocialShare.astro
Normal file
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
const { text, url, class: className = 'inline-block' } = Astro.props;
|
||||
---
|
||||
|
||||
<div class={className}>
|
||||
<span class="align-super font-bold">Share:</span>
|
||||
<button class="ml-2" title="Twitter Share" data-aw-social-share="twitter" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:twitter" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Facebook Share" data-aw-social-share="facebook" data-aw-url={url}
|
||||
><Icon name="logos:facebook" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Linkedin Share" data-aw-social-share="linkedin" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:linkedin-icon" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Whatsapp Share" data-aw-social-share="whatsapp" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="logos:whatsapp" class="w-6 h-6" />
|
||||
</button>
|
||||
<button class="ml-2" title="Email Share" data-aw-social-share="mail" data-aw-url={url} data-aw-text={text}
|
||||
><Icon name="tabler:mail" class="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
17
src/components/atoms/Tags.astro
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
import { getPermalink } from '~/utils/permalinks';
|
||||
|
||||
const { tags, class: className = 'text-sm' } = Astro.props;
|
||||
---
|
||||
|
||||
{
|
||||
tags && Array.isArray(tags) && (
|
||||
<ul class={className}>
|
||||
{tags.map((tag) => (
|
||||
<li class="bg-gray-100 dark:bg-slate-700 inline-block mr-2 mb-2 py-0.5 px-2">
|
||||
<a href={getPermalink(tag, 'tag')}>{tag}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
9
src/components/blog/Grid.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import Item from '~/components/blog/GridItem.astro';
|
||||
|
||||
const { posts } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="grid gap-6 row-gap-5 md:grid-cols-2 lg:grid-cols-4 -mb-6">
|
||||
{posts.map((post) => <Item post={post} />)}
|
||||
</div>
|
36
src/components/blog/GridItem.astro
Normal file
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
import { Picture } from '@astrojs/image/components'
|
||||
|
||||
import { findImage } from '~/utils/images';
|
||||
import { getPermalink } from '~/utils/permalinks';
|
||||
|
||||
const { post } = Astro.props;
|
||||
|
||||
const image = await findImage(post.image);
|
||||
---
|
||||
|
||||
<article class="mb-6 transition">
|
||||
<div class="relative h-0 pb-[56.25%] lg:h-64 overflow-hidden bg-gray-400 dark:bg-slate-700 rounded shadow-lg mb-6">
|
||||
{
|
||||
image && (
|
||||
<Picture
|
||||
src={image}
|
||||
class="object-cover w-full lg:h-64 rounded shadow-lg bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.title}
|
||||
aspectRatio="16:9"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<h3 class="mb-2 text-xl font-bold leading-snug sm:text-2xl font-heading">
|
||||
<a
|
||||
href={getPermalink(post.slug, 'post')}
|
||||
class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200"
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
</h3>
|
||||
<p class="text-gray-700 dark:text-gray-400">{post.excerpt || post.description}</p>
|
||||
</article>
|
29
src/components/blog/HighlightedPosts.astro
Normal file
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
import Grid from '~/components/blog/Grid.astro';
|
||||
|
||||
import { findPostsByIds } from '~/utils/posts';
|
||||
|
||||
const ids = [
|
||||
'get-started-website-with-astro-tailwind-css',
|
||||
'how-to-customize-astrowind-to-your-brand',
|
||||
'useful-resources-to-create-websites',
|
||||
'astrowind-template-in-depth',
|
||||
];
|
||||
const posts = await findPostsByIds(ids);
|
||||
---
|
||||
|
||||
<section class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
|
||||
<div class="flex flex-col mb-6 lg:justify-between lg:flex-row md:mb-8">
|
||||
<h2 class="max-w-lg mb-2 text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none lg:mb-5 group font-heading">
|
||||
<span class="inline-block mb-1 sm:mb-4">Find out more content<br class="hidden md:block" /> in our Blog</span>
|
||||
</h2>
|
||||
|
||||
<p class="text-gray-700 dark:text-slate-400 lg:text-sm lg:max-w-md">
|
||||
The blog will be used to display AstroWind documentation. Each new article will be an important step that you will
|
||||
need to know to be an expert in creating a website using Astro + Tailwind CSS The blog does not exist yet, but
|
||||
very soon. Astro is a very interesting technology. Thanks.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Grid posts={posts} />
|
||||
</section>
|
24
src/components/blog/LatestPosts.astro
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
import Grid from '~/components/blog/Grid.astro';
|
||||
|
||||
import { findLatestPosts } from '~/utils/posts';
|
||||
|
||||
const count = 4;
|
||||
const posts = await findLatestPosts({ count });
|
||||
---
|
||||
|
||||
<section class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
|
||||
<div class="flex flex-col mb-6 lg:justify-between lg:flex-row md:mb-8">
|
||||
<h2 class="max-w-lg mb-2 text-3xl font-bold tracking-tight sm:text-4xl sm:leading-none lg:mb-5 group font-heading">
|
||||
<span class="inline-block mb-1 sm:mb-4">Latest articles<br class="hidden md:block" /> in our Blog</span>
|
||||
</h2>
|
||||
|
||||
<p class="text-gray-700 dark:text-slate-400 lg:text-sm lg:max-w-md">
|
||||
The blog will be used to display AstroWind documentation. Each new article will be an important step that you will
|
||||
need to know to be an expert in creating a website using Astro + Tailwind CSS The blog does not exist yet, but
|
||||
very soon. Astro is a very interesting technology. Thanks.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Grid posts={posts} />
|
||||
</section>
|
15
src/components/blog/List.astro
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
import Item from '~/components/blog/ListItem.astro';
|
||||
|
||||
const { posts } = Astro.props;
|
||||
---
|
||||
|
||||
<ul>
|
||||
{
|
||||
posts.map((post) => (
|
||||
<li class="mb-10 md:mb-16">
|
||||
<Item post={post} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
59
src/components/blog/ListItem.astro
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
import { Picture } from '@astrojs/image/components';
|
||||
import PostTags from '~/components/atoms/Tags.astro';
|
||||
|
||||
import { getPermalink } from '~/utils/permalinks';
|
||||
import { findImage } from '~/utils/images';
|
||||
import { getFormattedDate } from '~/utils/utils';
|
||||
|
||||
const { post } = Astro.props;
|
||||
|
||||
const image = await findImage(post.image);
|
||||
---
|
||||
|
||||
<article class={`max-w-md mx-auto md:max-w-none grid gap-6 md:gap-8 ${image ? 'md:grid-cols-2' : ''}`}>
|
||||
{
|
||||
image && (
|
||||
<a class="relative block group" href={getPermalink(post.slug, 'post')}>
|
||||
<div class="relative h-0 pb-[56.25%] md:pb-[75%] md:h-80 lg:pb-[56.25%] overflow-hidden bg-gray-400 dark:bg-slate-700 rounded shadow-lg">
|
||||
{image && (
|
||||
<Picture
|
||||
src={image}
|
||||
class="absolute inset-0 object-cover w-full h-full mb-6 rounded shadow-lg bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.title}
|
||||
aspectRatio="16:9"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<div>
|
||||
<header>
|
||||
<h2 class="text-xl sm:text-2xl font-bold leading-snug mb-2 font-heading">
|
||||
<a
|
||||
class="hover:text-primary-600 underline underline-offset-4 decoration-1 decoration-dotted transition ease-in duration-200"
|
||||
href={getPermalink(post.slug, 'post')}
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
</h2>
|
||||
</header>
|
||||
<p class="text-md sm:text-lg flex-grow">
|
||||
{post.excerpt || post.description}
|
||||
</p>
|
||||
<footer class="mt-4">
|
||||
<div>
|
||||
<span class="text-gray-500 dark:text-slate-400">
|
||||
<time datetime={post.publishDate}>{getFormattedDate(post.publishDate)}</time> ~
|
||||
{Math.ceil(post.readingTime)} min read
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<PostTags tags={post.tags} />
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</article>
|
57
src/components/blog/SinglePost.astro
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
import { Picture } from '@astrojs/image/components'
|
||||
import PostTags from '~/components/atoms/Tags.astro';
|
||||
import SocialShare from '~/components/atoms/SocialShare.astro';
|
||||
|
||||
import { getFormattedDate } from '~/utils/utils';
|
||||
|
||||
const { post, url } = Astro.props;
|
||||
---
|
||||
|
||||
<section class="py-8 sm:py-16 lg:py-20 mx-auto">
|
||||
<article>
|
||||
<header class={post.image ? 'text-center' : ''}>
|
||||
<p class="px-4 sm:px-6 max-w-3xl mx-auto">
|
||||
<time datetime={post.publishDate}>{getFormattedDate(post.publishDate)}</time> ~ {Math.ceil(post.readingTime)} min
|
||||
read
|
||||
</p>
|
||||
<h1
|
||||
class="px-4 sm:px-6 max-w-3xl mx-auto text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-8 font-heading"
|
||||
>
|
||||
{post.title}
|
||||
</h1>
|
||||
{
|
||||
post.image ? (
|
||||
<Picture
|
||||
src={post.image}
|
||||
class="max-w-full lg:max-w-6xl mx-auto mt-4 mb-6 sm:rounded-md bg-gray-400 dark:bg-slate-700"
|
||||
widths={[400, 900]}
|
||||
sizes="(max-width: 900px) 400px, 900px"
|
||||
alt={post.description}
|
||||
loading="eager"
|
||||
aspectRatio={16/9}
|
||||
width={900}
|
||||
height={506}
|
||||
/>
|
||||
) : (
|
||||
<div class="max-w-3xl mx-auto px-4 sm:px-6">
|
||||
<div class="border-t dark:border-slate-700" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</header>
|
||||
<div
|
||||
class="container mx-auto px-6 sm:px-6 max-w-3xl prose prose-lg lg:prose-xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:font-heading prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-primary-600 dark:prose-a:text-primary-400 prose-img:rounded-md prose-img:shadow-lg mt-8"
|
||||
>
|
||||
{post.Content ? <post.Content /> : <Fragment set:html={post.body} />}
|
||||
</div>
|
||||
<div class="container mx-auto px-6 sm:px-6 max-w-3xl mt-8 flex justify-between flex-col sm:flex-row">
|
||||
<PostTags tags={post.tags} class="mr-5" />
|
||||
<SocialShare
|
||||
url={url}
|
||||
text={post.title}
|
||||
class="mt-5 sm:mt-1 align-middle text-gray-500 dark:text-slate-600"
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
83
src/components/core/BasicScripts.astro
Normal file
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
---
|
||||
|
||||
<script is:inline>
|
||||
// Set "light" theme as default
|
||||
// if (!localStorage.theme) {
|
||||
// localStorage.theme = "light";
|
||||
// }
|
||||
|
||||
if (
|
||||
localStorage.theme === 'dark' ||
|
||||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
|
||||
function attachEvent(selector, event, fn) {
|
||||
const matches = document.querySelectorAll(selector);
|
||||
if (matches && matches.length) {
|
||||
matches.forEach((elem) => {
|
||||
elem.addEventListener(event, () => fn(elem), false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function () {
|
||||
attachEvent('[data-aw-toggle-menu]', 'click', function (elem) {
|
||||
elem.classList.toggle('expanded');
|
||||
document.body.classList.toggle('overflow-hidden');
|
||||
document.getElementById('header')?.classList.toggle('h-screen');
|
||||
document.querySelector('#header nav')?.classList.toggle('hidden');
|
||||
});
|
||||
|
||||
attachEvent('[data-aw-toggle-color-scheme]', 'click', function () {
|
||||
document.documentElement.classList.toggle('dark');
|
||||
localStorage.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
|
||||
});
|
||||
|
||||
attachEvent('[data-aw-social-share]', 'click', function (elem) {
|
||||
const network = elem.getAttribute('data-aw-social-share');
|
||||
const url = encodeURIComponent(elem.getAttribute('data-aw-url'));
|
||||
const text = encodeURIComponent(elem.getAttribute('data-aw-text'));
|
||||
|
||||
let href;
|
||||
switch (network) {
|
||||
case 'facebook':
|
||||
href = `https://www.facebook.com/sharer.php?u=${url}`;
|
||||
break;
|
||||
case 'twitter':
|
||||
href = `https://twitter.com/intent/tweet?url=${url}&text=${text}`;
|
||||
break;
|
||||
case 'linkedin':
|
||||
href = `https://www.linkedin.com/shareArticle?mini=true&url=${url}&title=${text}`;
|
||||
break;
|
||||
case 'whatsapp':
|
||||
href = `https://wa.me/?text=${text}%20${url}`;
|
||||
break;
|
||||
case 'mail':
|
||||
href = `mailto:?subject=%22${text}%22&body=${text}%20${url}`;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
const newlink = document.createElement('a');
|
||||
newlink.target = '_blank';
|
||||
newlink.href = href;
|
||||
newlink.click();
|
||||
});
|
||||
};
|
||||
window.onpageshow = function () {
|
||||
const elem = document.querySelector('[data-aw-toggle-menu]');
|
||||
if (elem) {
|
||||
elem.classList.remove('expanded');
|
||||
}
|
||||
document.body.classList.remove('overflow-hidden');
|
||||
document.getElementById('header')?.classList.remove('h-screen');
|
||||
document.querySelector('#header nav')?.classList.add('hidden');
|
||||
};
|
||||
</script>
|
82
src/components/core/MetaTags.astro
Normal file
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
import { AstroSeo } from '@astrolib/seo';
|
||||
import { GoogleAnalytics } from '@astrolib/analytics';
|
||||
import { getImage } from '@astrojs/image';
|
||||
import { getRelativeUrlByFilePath } from '~/utils/directories';
|
||||
|
||||
import defaultImageSrc from '~/assets/images/default.png';
|
||||
|
||||
import { SITE } from '~/config.mjs';
|
||||
import Fonts from '../atoms/Fonts.astro';
|
||||
import ExtraMetaTags from '../atoms/ExtraMetaTags.astro';
|
||||
import SplitbeeAnalytics from './SplitbeeAnalytics.astro';
|
||||
|
||||
const { src: defaultImage } = await getImage({
|
||||
src: defaultImageSrc,
|
||||
width: 1200,
|
||||
height: 628,
|
||||
});
|
||||
|
||||
const {
|
||||
title = SITE.name,
|
||||
description = '',
|
||||
image: _image = defaultImage,
|
||||
|
||||
canonical,
|
||||
noindex = false,
|
||||
nofollow = false,
|
||||
|
||||
ogTitle = title,
|
||||
ogType = 'website',
|
||||
} = Astro.props;
|
||||
|
||||
const image =
|
||||
typeof _image === 'string'
|
||||
? new URL(_image, Astro.site)
|
||||
: _image && typeof _image['src'] !== 'undefined'
|
||||
? new URL(getRelativeUrlByFilePath(_image.src), Astro.site)
|
||||
: null;
|
||||
---
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<AstroSeo
|
||||
title={title}
|
||||
description={description}
|
||||
canonical={canonical}
|
||||
noindex={noindex}
|
||||
nofollow={nofollow}
|
||||
openGraph={{
|
||||
url: canonical,
|
||||
title: ogTitle,
|
||||
description: description,
|
||||
type: ogType,
|
||||
images: image
|
||||
? [
|
||||
{
|
||||
url: image.toString(),
|
||||
alt: ogTitle,
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
// site_name: 'SiteName',
|
||||
}}
|
||||
twitter={{
|
||||
// handle: '@handle',
|
||||
// site: '@site',
|
||||
cardType: image ? 'summary_large_image' : undefined,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Fonts />
|
||||
|
||||
<!-- Google Site Verification -->
|
||||
{SITE.googleSiteVerificationId && <meta name="google-site-verification" content={SITE.googleSiteVerificationId} />}
|
||||
|
||||
<!-- Google Analytics -->
|
||||
{SITE.googleAnalyticsId && <GoogleAnalytics id={String(SITE.googleAnalyticsId)} partytown={true} />}
|
||||
|
||||
{SITE.splitbeeAnalytics?.enabled && <SplitbeeAnalytics {...SITE.splitbeeAnalytics} />}
|
||||
|
||||
<ExtraMetaTags />
|
6
src/components/core/SplitbeeAnalytics.astro
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
const { doNotTrack = true, noCookieMode = false, url = 'https://cdn.splitbee.io/sb.js' } = Astro.props;
|
||||
---
|
||||
|
||||
<!-- Splitbee Analytics -->
|
||||
<script data-respect-dnt={doNotTrack} data-no-cookie={noCookieMode} async src={url}></script>
|
15
src/components/core/ToggleMenu.astro
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
const {
|
||||
label = 'Toggle Menu',
|
||||
class:
|
||||
className = 'ml-1.5 text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center transition',
|
||||
iconClass = 'w-6 h-6',
|
||||
iconName = 'tabler:menu',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<button type="button" class={className} aria-label={label} data-aw-toggle-menu>
|
||||
<Icon name={iconName} class={iconClass} optimize={false} />
|
||||
</button>
|
15
src/components/core/ToggleTheme.astro
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
const {
|
||||
label = 'Toggle between Dark and Light mode',
|
||||
class:
|
||||
className = 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center',
|
||||
iconClass = 'w-6 h-6',
|
||||
iconName = 'tabler:sun',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<button type="button" class={className} aria-label={label} data-aw-toggle-color-scheme>
|
||||
<Icon name={iconName} class={iconClass} />
|
||||
</button>
|
28
src/components/widgets/Announcement.astro
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
import { getPermalink } from '~/utils/permalinks';
|
||||
---
|
||||
|
||||
<div
|
||||
class="hidden md:block bg-primary-100 dark:bg-slate-800 dark:border-slate-800 dark:text-slate-400 border-b border-primary-100 text-sm px-3 py-2 text-gray-800 overflow-hidden whitespace-nowrap text-ellipsis"
|
||||
>
|
||||
<span class="text-xs py-0.5 px-1 bg-primary-200 dark:bg-slate-600 font-semibold">NEW</span>
|
||||
<a
|
||||
href={getPermalink('useful-resources-to-create-websites', 'post')}
|
||||
class="hover:underline text-gray-700 dark:text-slate-400"
|
||||
>Useful tools and resources to create a professional website »</a
|
||||
>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="float-right"
|
||||
title="If you like AstroWind, give us a star."
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
>
|
||||
<img
|
||||
src="https://img.shields.io/github/stars/onwidget/astrowind.svg?style=social&label=Stars&maxAge=86400"
|
||||
alt="Follow @onWidget"
|
||||
width="84"
|
||||
height="20"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
30
src/components/widgets/CallToAction.astro
Normal file
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
---
|
||||
|
||||
<section class="relative">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="max-w-3xl mx-auto text-center p-6 rounded-md shadow-xl dark:shadow-none">
|
||||
<h2 class="text-4xl md:text-4xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
<span>Astro</span> + <br class="block sm:hidden" /><span class="sm:whitespace-nowrap">Tailwind CSS</span>
|
||||
</h2>
|
||||
<p class="text-xl text-gray-600 dark:text-slate-400">
|
||||
Be very surprised by these huge fake numbers you are seeing on this page. <br class="hidden md:inline" />Don't
|
||||
waste more time! :P
|
||||
</p>
|
||||
|
||||
<div class="mt-6">
|
||||
<a
|
||||
class="btn btn-primary mb-4 sm:mb-0"
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<Icon name="tabler:download" class="w-5 h-5 mr-1 -ml-1.5" /> Get template
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
24
src/components/widgets/Error404.astro
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
import { getHomePermalink } from '~/utils/permalinks';
|
||||
---
|
||||
|
||||
<section class="flex items-center h-full p-16">
|
||||
<div class="container flex flex-col items-center justify-center px-5 mx-auto my-8">
|
||||
<div class="max-w-md text-center">
|
||||
<h2 class="mb-8 font-bold text-9xl">
|
||||
<span class="sr-only">Error</span>
|
||||
<span class="bg-clip-text text-transparent bg-gradient-to-r from-primary-500 to-secondary-500">404</span>
|
||||
</h2>
|
||||
<p class="text-3xl font-semibold md:text-3xl">Sorry, we couldn't find this page.</p>
|
||||
<p class="mt-4 mb-8 text-lg text-gray-600 dark:text-slate-400">
|
||||
But dont worry, you can find plenty of other things on our homepage.
|
||||
</p>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href={getHomePermalink()}
|
||||
class="btn ml-4"
|
||||
>Back to homepage</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
71
src/components/widgets/FAQs.astro
Normal file
|
@ -0,0 +1,71 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
const items = [
|
||||
[
|
||||
{
|
||||
question: 'What do I need to start?',
|
||||
answer: `Space, the final frontier. These are the voyages of the Starship Enterprise. Its five-year mission: to explore strange new worlds.
|
||||
|
||||
Many say exploration is part of our destiny, but it’s actually our duty to future generations.`,
|
||||
},
|
||||
{
|
||||
question: 'How to install the Astro + Tailwind CSS template?',
|
||||
answer: `Well, the way they make shows is, they make one show. That show's called a pilot.
|
||||
|
||||
Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows. Some pilots get picked and become television programs. Some don't, become nothing. She starred in one of the ones that became nothing.`,
|
||||
},
|
||||
{
|
||||
question: "What's something that you completely don't understand?",
|
||||
answer: `A flower in my garden, a mystery in my panties. Heart attack never stopped old Big Bear. I didn't even know we were calling him Big Bear.`,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
question: "What's an example of when you changed your mind?",
|
||||
answer: `Michael Knight a young loner on a crusade to champion the cause of the innocent. The helpless. The powerless in a world of criminals who operate above the law. Here he comes Here comes Speed Racer. He's a demon on wheels.`,
|
||||
},
|
||||
{
|
||||
question: 'What is something that you would really like to try again?',
|
||||
answer: `A business big enough that it could be listed on the NASDAQ goes belly up. Disappears!
|
||||
|
||||
It ceases to exist without me. No, you clearly don't know who you're talking to, so let me clue you in.`,
|
||||
},
|
||||
{
|
||||
question: 'If you could only ask one question to each person you meet, what would that question be?',
|
||||
answer: `This is not about revenge. This is about justice. A lot of things can change in twelve years, Admiral. Well, that's certainly good to know. About four years. I got tired of hearing how young I looked.`,
|
||||
},
|
||||
],
|
||||
];
|
||||
---
|
||||
|
||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:py-20">
|
||||
<div class="max-w-xl sm:mx-auto lg:max-w-2xl">
|
||||
<div class="max-w-xl mb-10 md:mx-auto sm:text-center lg:max-w-2xl md:mb-12">
|
||||
<h2 class="max-w-lg mb-4 text-3xl font-bold leading-none tracking-tight sm:text-4xl md:mx-auto font-heading">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-screen-xl sm:mx-auto">
|
||||
<div class="grid grid-cols-1 gap-x-8 gap-y-8 lg:gap-x-16 md:grid-cols-2">
|
||||
{
|
||||
items.map((subitems) => (
|
||||
<div class="space-y-8">
|
||||
{subitems.map(({ question, answer }) => (
|
||||
<div>
|
||||
<p class="mb-4 text-xl font-bold">
|
||||
<Icon name="tabler:arrow-down-right" class="w-7 h-7 text-primary-500 inline-block" />
|
||||
{question}
|
||||
</p>
|
||||
{answer.split('\n\n').map((paragraph) => (
|
||||
<p class="text-gray-700 dark:text-gray-400 mb-2" set:html={paragraph} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
82
src/components/widgets/Features.astro
Normal file
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
const items = [
|
||||
[
|
||||
{
|
||||
title: 'Astro + Tailwind CSS Integration',
|
||||
description:
|
||||
'A seamless integration between two great frameworks that offer high productivity, performance and versatility.',
|
||||
icon: 'tabler:brand-tailwind',
|
||||
},
|
||||
{
|
||||
title: 'Ready-to-use Components',
|
||||
description:
|
||||
'Widgets made with Tailwind CSS ready to be used in Marketing Websites, SaaS, Blogs, Personal Profiles, Small Business...',
|
||||
icon: 'tabler:components',
|
||||
},
|
||||
{
|
||||
title: 'Best Practices',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||
icon: 'tabler:list-check',
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
title: 'Excellent Page Speed',
|
||||
description:
|
||||
'Having a good page speed impacts organic search ranking, improves user experience (UI/UX) and increase conversion rates.',
|
||||
icon: 'tabler:rocket',
|
||||
},
|
||||
{
|
||||
title: 'Search Engine Optimization (SEO)',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||
icon: 'tabler:arrows-right-left',
|
||||
},
|
||||
{
|
||||
title: 'Open to new ideas and contributions',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi risus tempus nulla.',
|
||||
icon: 'tabler:bulb',
|
||||
},
|
||||
],
|
||||
];
|
||||
---
|
||||
|
||||
<section class="scroll-mt-16" id="features">
|
||||
<div class="px-4 py-16 mx-auto max-w-6xl lg:px-8 lg:py-20">
|
||||
<div class="mb-10 md:mx-auto sm:text-center md:mb-12 max-w-3xl">
|
||||
<p class="text-base text-primary-600 dark:text-primary-200 font-semibold tracking-wide uppercase">Features</p>
|
||||
<h2 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
What you get with <span class="whitespace-nowrap">AstroWind</span>
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto sm:text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque rem aperiam, eaque ipsa
|
||||
quae.
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid mx-auto space-y-6 md:grid-cols-2 md:space-y-0">
|
||||
{
|
||||
items.map((subitems) => (
|
||||
<div class="space-y-8 sm:px-8">
|
||||
{subitems.map(({ title, description, icon }) => (
|
||||
<div class="flex flex-row max-w-md">
|
||||
<div class="mb-4 mr-4">
|
||||
<div class="flex items-center justify-center w-12 h-12 rounded-full bg-primary-500 dark:bg-primary-700">
|
||||
{icon && <Icon name={icon} class="w-6 h-6 text-white icon-light" />}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="mb-3 text-xl font-bold">{title}</h3>
|
||||
<p class="text-gray-600 dark:text-slate-400">{description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
73
src/components/widgets/Features2.astro
Normal file
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
|
||||
const items = [
|
||||
{
|
||||
title: 'Headers',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.',
|
||||
icon: 'flat-color-icons:home',
|
||||
},
|
||||
{
|
||||
title: 'Footers',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.',
|
||||
icon: 'flat-color-icons:faq',
|
||||
},
|
||||
{
|
||||
title: 'Features',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.',
|
||||
icon: 'flat-color-icons:video-projector',
|
||||
},
|
||||
{
|
||||
title: 'Call-to-Action',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.',
|
||||
icon: 'flat-color-icons:video-projector',
|
||||
},
|
||||
{
|
||||
title: 'Pricing',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.',
|
||||
icon: 'flat-color-icons:calculator',
|
||||
},
|
||||
{
|
||||
title: 'Testimonial',
|
||||
description:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.',
|
||||
icon: 'flat-color-icons:voice-presentation',
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<section class="relative">
|
||||
<div class="absolute inset-0 bg-primary-50 dark:bg-slate-800 pointer-events-none mb-32" aria-hidden="true"></div>
|
||||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-4 pt-8 sm:py-6 lg:py-8 lg:pt-12">
|
||||
<div class="mb-8 text-center">
|
||||
<p class="text-base text-primary-600 dark:text-primary-200 font-semibold tracking-wide uppercase">Components</p>
|
||||
<h2 class="text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
Most used widgets
|
||||
</h2>
|
||||
<p class="max-w-3xl mx-auto text-center text-xl text-gray-600 dark:text-slate-400">
|
||||
Provides frequently used components for building websites using Tailwind CSS
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3 items-start my-12 dark:text-white">
|
||||
{
|
||||
items.map(({ title, description, icon }) => (
|
||||
<div class="relative flex flex-col p-6 bg-white dark:bg-slate-900 rounded shadow-xl hover:shadow-lg transition dark:border dark:border-slate-800">
|
||||
<div class="flex items-center mb-4">
|
||||
<Icon name={icon} class="w-12 h-12" />
|
||||
|
||||
<div class="ml-4 text-xl font-bold">{title}</div>
|
||||
</div>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-md">{description}</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
90
src/components/widgets/Features3.astro
Normal file
|
@ -0,0 +1,90 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
---
|
||||
|
||||
<section>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 overflow-hidden">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="py-4 sm:py-6 lg:py-8">
|
||||
<div class="flex flex-wrap md:-mx-8">
|
||||
<div class="w-full lg:w-1/2 px-0 sm:px-8">
|
||||
<div class="mb-12 lg:mb-0 pb-12 lg:pb-0 border-b lg:border-b-0">
|
||||
<h2 class="mb-4 text-3xl lg:text-4xl font-bold font-heading">
|
||||
Sed ac magna sit amet risus tristique interdum, at vel velit in hac habitasse platea dictumst.
|
||||
</h2>
|
||||
|
||||
<p class="mb-8 text-xl text-gray-600 dark:text-slate-400">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi
|
||||
risus tempus nulla, sed porttitor est nibh at nulla. Praesent placerat enim ut ex tincidunt vehicula.
|
||||
Fusce sit amet dui tellus.
|
||||
</p>
|
||||
|
||||
<div class="w-full">
|
||||
<a
|
||||
class="btn btn-primary mb-4 sm:mb-0"
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<Icon name="tabler:download" class="w-5 h-5 mr-1 -ml-1.5" /> Get template
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full lg:w-1/2 px-0 sm:px-8">
|
||||
<ul class="space-y-12">
|
||||
<li class="flex md:-mx-4">
|
||||
<div class="pr-4 sm:pl-4">
|
||||
<span
|
||||
class="flex w-16 h-16 mx-auto items-center justify-center text-2xl font-bold rounded-full bg-primary-50 text-primary-600"
|
||||
>
|
||||
1</span
|
||||
>
|
||||
</div>
|
||||
<div class="px-4">
|
||||
<h3 class="mb-4 text-xl font-semibold font-heading">Responsive Elements</h3>
|
||||
<p class="text-gray-500 dark:text-gray-400">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis
|
||||
lobortis, mi risus tempus nulla.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex md:-mx-4">
|
||||
<div class="pr-4 sm:pl-4">
|
||||
<span
|
||||
class="flex w-16 h-16 mx-auto items-center justify-center text-2xl font-bold rounded-full bg-primary-50 text-primary-600"
|
||||
>
|
||||
2</span
|
||||
>
|
||||
</div>
|
||||
<div class="px-4">
|
||||
<h3 class="mb-4 text-xl font-semibold font-heading">Flexible Team</h3>
|
||||
<p class="text-gray-500 dark:text-gray-400">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis
|
||||
lobortis, mi risus tempus nulla.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex md:-mx-4">
|
||||
<div class="pr-4 sm:pl-4">
|
||||
<span
|
||||
class="flex w-16 h-16 mx-auto items-center justify-center text-2xl font-bold rounded-full bg-primary-50 text-primary-600"
|
||||
>
|
||||
3</span
|
||||
>
|
||||
</div>
|
||||
<div class="px-4">
|
||||
<h3 class="mb-4 text-xl font-semibold font-heading">Ecologic Software</h3>
|
||||
<p class="text-gray-500 dark:text-gray-400">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis
|
||||
lobortis, mi risus tempus nulla.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
128
src/components/widgets/Footer.astro
Normal file
|
@ -0,0 +1,128 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
import { getHomePermalink, getRelativeLink } from '~/utils/permalinks';
|
||||
|
||||
const links = [
|
||||
{
|
||||
title: 'Product',
|
||||
items: [
|
||||
{ title: 'Features', href: '#' },
|
||||
{ title: 'Security', href: '#' },
|
||||
{ title: 'Team', href: '#' },
|
||||
{ title: 'Enterprise', href: '#' },
|
||||
{ title: 'Customer stories', href: '#' },
|
||||
{ title: 'Pricing', href: '#' },
|
||||
{ title: 'Resources', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Platform',
|
||||
items: [
|
||||
{ title: 'Developer API', href: '#' },
|
||||
{ title: 'Partners', href: '#' },
|
||||
{ title: 'Atom', href: '#' },
|
||||
{ title: 'Electron', href: '#' },
|
||||
{ title: 'AstroWind Desktop', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Support',
|
||||
items: [
|
||||
{ title: 'Docs', href: '#' },
|
||||
{ title: 'Community Forum', href: '#' },
|
||||
{ title: 'Professional Services', href: '#' },
|
||||
{ title: 'Skills', href: '#' },
|
||||
{ title: 'Status', href: '#' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Company',
|
||||
items: [
|
||||
{ title: 'About', href: '#' },
|
||||
{ title: 'Blog', href: '#' },
|
||||
{ title: 'Careers', href: '#' },
|
||||
{ title: 'Press', href: '#' },
|
||||
{ title: 'Inclusion', href: '#' },
|
||||
{ title: 'Social Impact', href: '#' },
|
||||
{ title: 'Shop', href: '#' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const social = [
|
||||
{ label: 'Twitter', icon: 'tabler:brand-twitter', href: '#' },
|
||||
{ label: 'Instagram', icon: 'tabler:brand-instagram', href: '#' },
|
||||
{ label: 'Facebook', icon: 'tabler:brand-facebook', href: '#' },
|
||||
{ label: 'RSS', icon: 'tabler:rss', href: getRelativeLink('/rss.xml') },
|
||||
{ label: 'Github', icon: 'tabler:brand-github', href: 'https://github.com/onwidget/astrowind' },
|
||||
];
|
||||
---
|
||||
|
||||
<footer class="border-t border-gray-200 dark:border-slate-800">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="grid grid-cols-12 gap-4 gap-y-8 sm:gap-8 py-8 md:py-12">
|
||||
<div class="col-span-12 lg:col-span-4">
|
||||
<div class="mb-2">
|
||||
<a class="inline-block font-bold text-xl" href={getHomePermalink()}>AstroWind</a>
|
||||
</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 dark:text-gray-400 hover:underline transition duration-150 ease-in-out"
|
||||
href="#">Terms</a
|
||||
> ·
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 dark:text-gray-400 hover:underline transition duration-150 ease-in-out"
|
||||
href="#">Privacy Policy</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
links.map(({ title, items }) => (
|
||||
<div class="col-span-6 md:col-span-3 lg:col-span-2">
|
||||
<div class="text-gray-800 dark:text-gray-300 font-medium mb-2">{title}</div>
|
||||
{items && Array.isArray(items) && items.length > 0 && (
|
||||
<ul class="text-sm">
|
||||
{items.map(({ title, href }) => (
|
||||
<li class="mb-2">
|
||||
<a
|
||||
class="text-gray-600 hover:text-gray-700 hover:underline dark:text-gray-400 transition duration-150 ease-in-out"
|
||||
href={href}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="md:flex md:items-center md:justify-between py-6 md:py-8">
|
||||
<ul class="flex mb-4 md:order-1 -ml-2 md:ml-4 md:mb-0">
|
||||
{
|
||||
social.map(({ label, href, icon }) => (
|
||||
<li>
|
||||
<a
|
||||
class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center"
|
||||
aria-label={label}
|
||||
href={href}
|
||||
>
|
||||
<Icon name={icon} class="w-5 h-5" />
|
||||
</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
||||
<div class="text-sm text-gray-700 mr-4 dark:text-slate-400">
|
||||
<span
|
||||
class="w-5 h-5 md:w-6 md:h-6 md:-mt-0.5 bg-cover mr-1.5 float-left rounded-sm bg-[url(https://onwidget.com/favicon/favicon-32x32.png)]"
|
||||
>
|
||||
</span>
|
||||
Made by <a class="text-blue-600 hover:underline dark:text-gray-200" href="https://onwidget.com/"> onWidget</a> ·
|
||||
All rights reserved.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
95
src/components/widgets/Header.astro
Normal file
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
import Logo from '~/components/atoms/Logo.astro';
|
||||
import ToggleTheme from '~/components/core/ToggleTheme.astro';
|
||||
import ToggleMenu from '~/components/core/ToggleMenu.astro';
|
||||
|
||||
import { getHomePermalink, getBlogPermalink, getPermalink, getRelativeLink } from '~/utils/permalinks';
|
||||
---
|
||||
|
||||
<header
|
||||
class="sticky top-0 z-40 flex-none mx-auto w-full bg-white md:bg-white/90 dark:bg-slate-900 dark:md:bg-slate-900/90 md:backdrop-blur-sm"
|
||||
id="header"
|
||||
>
|
||||
<div class="py-3 px-3 mx-auto w-full md:flex md:justify-between max-w-6xl md:px-4">
|
||||
<div class="flex justify-between">
|
||||
<a class="flex items-center" href={getHomePermalink()}>
|
||||
<Logo />
|
||||
</a>
|
||||
<div class="flex items-center md:hidden">
|
||||
<ToggleTheme />
|
||||
<ToggleMenu />
|
||||
</div>
|
||||
</div>
|
||||
<nav
|
||||
class="items-center w-full md:w-auto hidden md:flex text-gray-600 dark:text-slate-200 h-[calc(100vh-100px)] md:h-auto overflow-y-auto md:overflow-visible"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<ul class="flex flex-col pt-8 md:pt-0 md:flex-row md:self-center w-full md:w-auto text-xl md:text-base">
|
||||
<li class="dropdown">
|
||||
<button
|
||||
class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
>Pages</button
|
||||
>
|
||||
<ul
|
||||
class="dropdown-menu rounded md:absolute pl-4 md:pl-0 md:hidden font-medium md:bg-white md:min-w-[200px] dark:md:bg-slate-800 drop-shadow-xl"
|
||||
>
|
||||
<li class="">
|
||||
<a
|
||||
class="rounded-t md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-4 block whitespace-no-wrap"
|
||||
href="#">Features</a>
|
||||
</li>
|
||||
<li class="">
|
||||
<a class="md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-4 block whitespace-no-wrap" href="#"
|
||||
>Profile</a>
|
||||
</li>
|
||||
<li class="">
|
||||
<a
|
||||
class="rounded-b md:hover:bg-gray-100 dark:hover:bg-gray-700 py-2 px-4 block whitespace-no-wrap"
|
||||
href="#">Pricing</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href={getPermalink('useful-resources-to-create-websites', 'post')}
|
||||
>Resources
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="font-medium hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href={getBlogPermalink()}>Blog</a
|
||||
>
|
||||
</li>
|
||||
<li class="md:hidden">
|
||||
<a
|
||||
class="font-bold hover:text-gray-900 dark:hover:text-white px-4 py-3 flex items-center transition duration-150 ease-in-out"
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
>Github
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="md:self-center flex items-center mb-4 md:mb-0 ml-2">
|
||||
<div class="hidden items-center md:flex">
|
||||
<ToggleTheme iconClass="w-5 h-5" />
|
||||
<a
|
||||
class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 inline-flex items-center"
|
||||
aria-label="RSS Feed"
|
||||
href={getRelativeLink('/rss.xml')}
|
||||
>
|
||||
<Icon name="tabler:rss" class="w-5 h-5" />
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5"
|
||||
aria-label="Astrowind Github"
|
||||
>
|
||||
<Icon name="tabler:brand-github" class="w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
63
src/components/widgets/Hero.astro
Normal file
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
import { Picture } from '@astrojs/image/components'
|
||||
---
|
||||
|
||||
<section>
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||||
<div class="py-12 md:py-20">
|
||||
<div class="text-center pb-10 md:pb-16 max-w-5xl mx-auto">
|
||||
<h1 class="text-5xl md:text-[3.50rem] font-bold leading-tighter tracking-tighter mb-4 font-heading">
|
||||
Your website with
|
||||
<span>Astro</span> +
|
||||
<span
|
||||
class="sm:whitespace-nowrap"
|
||||
>Tailwind CSS</span
|
||||
>
|
||||
</h1>
|
||||
<div class="max-w-3xl mx-auto">
|
||||
<p class="text-xl text-gray-600 mb-8 dark:text-slate-400">
|
||||
<span class="font-semibold underline decoration-wavy decoration-1 decoration-primary-600 underline-offset-2">AstroWind</span> is a production ready template to start your new website using <em>Astro</em> + <em>Tailwind CSS</em>. It has been
|
||||
designed following Best Practices, SEO, Accessibility, <span class="inline sm:hidden">...</span><span
|
||||
class="hidden sm:inline"
|
||||
>Dark Mode, Great Page Speed, image optimization, sitemap generation and more.</span
|
||||
>
|
||||
</p>
|
||||
<div class="max-w-xs sm:max-w-md m-auto flex flex-nowrap flex-col sm:flex-row sm:justify-center gap-4">
|
||||
<div class="flex w-full sm:w-auto">
|
||||
<a
|
||||
class="btn btn-primary sm:mb-0 w-full"
|
||||
href="https://github.com/onwidget/astrowind"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<Icon name="tabler:download" class="w-5 h-5 mr-1 -ml-1.5" /> Get template
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex w-full sm:w-auto">
|
||||
<a
|
||||
class="btn w-full"
|
||||
href="#features">Learn more</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="relative m-auto max-w-4xl">
|
||||
<Picture
|
||||
src={import('~/assets/images/hero.jpg')}
|
||||
class="mx-auto rounded-md w-full"
|
||||
widths={[400, 768, 1480]}
|
||||
sizes="(max-width: 767px) 400px, (max-width: 1479px) 768px, 1480px"
|
||||
alt="Hero Image"
|
||||
aspectRatio={1480/833}
|
||||
loading="eager"
|
||||
width={1480}
|
||||
height={833}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
10
src/components/widgets/Note.astro
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
---
|
||||
|
||||
<section class="bg-primary-100 dark:bg-slate-800">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 py-4 text-md text-center font-medium">
|
||||
<span class="font-bold"> <Icon name="tabler:info-square" class="w-5 h-5 inline-block align-text-bottom" /> Philosophy:</span> Simplicity, Best
|
||||
Practices and High Performance
|
||||
</div>
|
||||
</section>
|
274
src/components/widgets/Pricing.astro
Normal file
|
@ -0,0 +1,274 @@
|
|||
---
|
||||
---
|
||||
|
||||
<!-- Pricing -->
|
||||
<div class="max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 mx-auto">
|
||||
<!-- Title -->
|
||||
<div class="max-w-2xl mx-auto text-center mb-10 lg:mb-14">
|
||||
<h2 class="text-2xl font-bold md:text-4xl md:leading-tight dark:text-white">Pricing</h2>
|
||||
<p class="mt-1 text-gray-600 dark:text-gray-400">
|
||||
Whatever your status, our offers evolve according to your needs.
|
||||
</p>
|
||||
</div>
|
||||
<!-- End Title -->
|
||||
|
||||
<!-- Grid -->
|
||||
<div class="mt-12 grid sm:grid-cols-2 lg:grid-cols-4 gap-6 lg:items-center">
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Free</h4>
|
||||
<span class="mt-7 font-bold text-5xl text-gray-800 dark:text-gray-200">Free</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Forever free</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 1 user</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border-2 border-blue-600 text-center shadow-xl rounded-xl p-8 dark:border-blue-500">
|
||||
<p class="mb-3">
|
||||
<span
|
||||
class="inline-flex items-center gap-1.5 py-1.5 px-3 rounded-md text-xs uppercase font-semibold bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-white"
|
||||
>Most popular</span
|
||||
>
|
||||
</p>
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Startup</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
39
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">All the basics for starting a new business</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 2 users</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Team</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
89
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Everything you need for a growing business</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 5 users</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col border border-gray-200 text-center rounded-xl p-8 dark:border-gray-700">
|
||||
<h4 class="font-medium text-lg text-gray-800 dark:text-gray-200">Enterprise</h4>
|
||||
<span class="mt-5 font-bold text-5xl text-gray-800 dark:text-gray-200">
|
||||
<span class="font-bold text-2xl -mr-2">$</span>
|
||||
149
|
||||
</span>
|
||||
<p class="mt-2 text-sm text-gray-500">Advanced features for scaling your business</p>
|
||||
|
||||
<ul class="mt-7 space-y-2.5 text-sm">
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> 10 users</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Plan features</span>
|
||||
</li>
|
||||
|
||||
<li class="flex space-x-2">
|
||||
<svg
|
||||
class="flex-shrink-0 h-5 w-5 text-blue-600"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.5219 4.0949C11.7604 3.81436 12.181 3.78025 12.4617 4.01871C12.7422 4.25717 12.7763 4.6779 12.5378 4.95844L6.87116 11.6251C6.62896 11.91 6.1998 11.94 5.9203 11.6916L2.9203 9.02494C2.64511 8.78033 2.62032 8.35894 2.86493 8.08375C3.10955 7.80856 3.53092 7.78378 3.80611 8.02839L6.29667 10.2423L11.5219 4.0949Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
<span class="text-gray-800 dark:text-gray-400"> Product support</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button class="mt-5 btn">Sign up</button>
|
||||
</div>
|
||||
<!-- End Card -->
|
||||
</div>
|
||||
<!-- End Grid -->
|
||||
</div>
|
||||
<!-- End Pricing -->
|
25
src/components/widgets/Stats.astro
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
---
|
||||
|
||||
<div class="px-4 py-8 md:py-16 sm:px-6 mx-auto md:px-24 lg:px-8 lg:py-20 max-w-6xl">
|
||||
<div class="grid grid-cols-2 row-gap-8 md:grid-cols-4">
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 mb-10 md:mb-0">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-primary-500 font-heading">132K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">
|
||||
Downloads
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 mb-10 md:mb-0">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-primary-500 font-heading">24.8K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">Stars</p>
|
||||
</div>
|
||||
<div class="text-center md:border-r dark:md:border-slate-500 font-heading">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-primary-500">10.3K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">Forks</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div class="text-4xl font-bold lg:text-5xl xl:text-6xl text-primary-500 font-heading">48.4K</div>
|
||||
<p class="text-sm font-medium tracking-widest text-gray-800 dark:text-slate-400 uppercase lg:text-base">Users</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
89
src/components/widgets/Steps.astro
Normal file
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
import { Icon } from 'astro-icon';
|
||||
import { Picture } from '@astrojs/image/components'
|
||||
---
|
||||
|
||||
<section class="px-4 py-16 sm:px-6 mx-auto lg:px-8 lg:py-20 max-w-6xl">
|
||||
<div class="grid gap-6 row-gap-10 md:grid-cols-2">
|
||||
<div class="md:pb-6 md:pr-16">
|
||||
<h2 class="mb-8 text-3xl lg:text-4xl font-bold font-heading">
|
||||
Sed ac magna sit amet risus tristique interdum. hac.
|
||||
</h2>
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center mr-4">
|
||||
<div>
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-600 border-2">
|
||||
<Icon name="tabler:arrow-down" class="w-6 h-6 text-primary-600 dark:text-slate-200" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-px h-full bg-gray-300 dark:bg-slate-500"></div>
|
||||
</div>
|
||||
<div class="pt-1 pb-8">
|
||||
<p class="mb-2 text-xl font-bold text-gray-900 dark:text-slate-300">Step 1</p>
|
||||
<p class="text-gray-600 dark:text-slate-400">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi
|
||||
risus tempus nulla, sed porttitor est nibh at nulla. Praesent placerat enim ut ex tincidunt vehicula. Fusce
|
||||
sit amet dui tellus.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center mr-4">
|
||||
<div>
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-600 border-2">
|
||||
<Icon name="tabler:arrow-down" class="w-6 h-6 text-primary-600 dark:text-slate-200" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-px h-full bg-gray-300 dark:bg-slate-500"></div>
|
||||
</div>
|
||||
<div class="pt-1 pb-8">
|
||||
<p class="mb-2 text-xl font-bold text-gray-900 dark:text-slate-300">Step 2</p>
|
||||
<p class="text-gray-600 dark:text-slate-400">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi
|
||||
risus tempus nulla, sed porttitor est nibh at nulla.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center mr-4">
|
||||
<div>
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-600 border-2">
|
||||
<Icon name="tabler:arrow-down" class="w-6 h-6 text-primary-600 dark:text-slate-200" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-px h-full bg-gray-300 dark:bg-slate-500"></div>
|
||||
</div>
|
||||
<div class="pt-1 pb-8">
|
||||
<p class="mb-2 text-xl font-bold text-gray-900 dark:text-slate-300">Step 3</p>
|
||||
<p class="text-gray-600 dark:text-slate-400">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sagittis, quam nec venenatis lobortis, mi
|
||||
risus tempus nulla, sed porttitor est nibh at nulla.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center mr-4">
|
||||
<div>
|
||||
<div class="flex items-center justify-center w-10 h-10 rounded-full border-primary-600 border-2 bg-primary-600">
|
||||
<Icon name="tabler:check" class="w-6 h-6 text-white dark:text-slate-200" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-1">
|
||||
<p class="mb-2 text-xl font-bold text-gray-900 dark:text-slate-300">Ready!</p>
|
||||
<p class="text-gray-600 dark:text-slate-400"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<Picture
|
||||
class="inset-0 object-cover object-top w-full rounded-md shadow-lg md:absolute md:h-full bg-gray-400 dark:bg-slate-700"
|
||||
src={import('~/assets/images/astronaut.jpg')}
|
||||
widths={[400, 768]}
|
||||
sizes="(max-width: 768px) 100vw, 432px"
|
||||
alt="Astronaut"
|
||||
aspectRatio="432:768"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
38
src/config.mjs
Normal file
|
@ -0,0 +1,38 @@
|
|||
export const SITE = {
|
||||
name: 'AstroWind',
|
||||
|
||||
origin: 'https://astrowind.vercel.app',
|
||||
basePathname: '/',
|
||||
trailingSlash: false,
|
||||
|
||||
title: 'AstroWind — Your website with Astro + Tailwind CSS',
|
||||
description: '🚀 AstroWind is a free and ready to start template to make your website using Astro and Tailwind CSS.',
|
||||
|
||||
googleAnalyticsId: false, // or "G-XXXXXXXXXX",
|
||||
googleSiteVerificationId: 'orcPxI47GSa-cRvY11tUe6iGg2IO_RPvnA1q95iEM3M',
|
||||
};
|
||||
|
||||
export const BLOG = {
|
||||
disabled: false,
|
||||
postsPerPage: 4,
|
||||
|
||||
blog: {
|
||||
disabled: false,
|
||||
pathname: 'blog', // blog main path, you can change this to "articles" (/articles)
|
||||
},
|
||||
|
||||
post: {
|
||||
disabled: false,
|
||||
pathname: '', // empty for /some-post, value for /pathname/some-post
|
||||
},
|
||||
|
||||
category: {
|
||||
disabled: false,
|
||||
pathname: 'category', // set empty to change from /category/some-category to /some-category
|
||||
},
|
||||
|
||||
tag: {
|
||||
disabled: false,
|
||||
pathname: 'tag', // set empty to change from /tag/some-tag to /some-tag
|
||||
},
|
||||
};
|
1
src/env.d.ts
vendored
|
@ -1 +0,0 @@
|
|||
/// <reference types="astro/client" />
|
25
src/layouts/BaseLayout.astro
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
import '~/assets/styles/base.css';
|
||||
|
||||
import MetaTags from '~/components/core/MetaTags.astro';
|
||||
import BasicScripts from '~/components/core/BasicScripts.astro';
|
||||
|
||||
const { meta = {} } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="motion-safe:scroll-smooth 2xl:text-[20px]">
|
||||
<head>
|
||||
<MetaTags {...meta} />
|
||||
</head>
|
||||
|
||||
<body class="antialiased text-gray-900 dark:text-slate-300 tracking-tight bg-white dark:bg-slate-900">
|
||||
<slot />
|
||||
<BasicScripts />
|
||||
<style is:global>
|
||||
img {
|
||||
content-visibility: auto;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
18
src/layouts/BlogLayout.astro
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
import Layout from '~/layouts/PageLayout.astro';
|
||||
|
||||
const { meta } = Astro.props;
|
||||
---
|
||||
|
||||
<Layout {meta}>
|
||||
<section class="px-6 sm:px-6 py-12 sm:py-16 lg:py-20 mx-auto max-w-3xl">
|
||||
<header>
|
||||
<h1
|
||||
class="text-center text-4xl md:text-5xl font-bold leading-tighter tracking-tighter mb-8 md:mb-16 font-heading"
|
||||
>
|
||||
<slot name="title" />
|
||||
</h1>
|
||||
</header>
|
||||
<slot />
|
||||
</section>
|
||||
</Layout>
|
|
@ -1,57 +0,0 @@
|
|||
---
|
||||
import '../style.css';
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
|
||||
let pageTitle = title;
|
||||
if (pageTitle) {
|
||||
pageTitle += ' | Forgejo';
|
||||
} else {
|
||||
pageTitle = 'Forgejo';
|
||||
}
|
||||
|
||||
const base = import.meta.env.BASE_URL;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="text-gray-900 bg-gray-100">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{pageTitle}</title>
|
||||
</head>
|
||||
<body class="flex flex-col min-h-screen">
|
||||
<header class="bg-purple-900 text-white">
|
||||
<nav class="centered-content flex items-center">
|
||||
<a href={base} class="no-underline p-4 font-bold text-xl">🔨 Forgejo</a>
|
||||
<div class="flex-auto"></div>
|
||||
<a
|
||||
href="https://codeberg.org/forgejo/"
|
||||
class="no-underline p-3 bg-white/90 my-2 text-purple-900 rounded hover:bg-white">Shape me on Codeberg</a
|
||||
>
|
||||
</nav>
|
||||
</header>
|
||||
<slot />
|
||||
<footer class="border-t border-gray-200 text-sm text-gray-700">
|
||||
<div class="max-w-6xl mx-auto px-4 sm:px-6 flex py-4">
|
||||
<p class="flex-auto">
|
||||
© 2022 Forgejo authors, content available under <a href="https://creativecommons.org/licenses/by-sa/4.0/"
|
||||
>CC BY-SA 4.0</a
|
||||
>, unless stated otherwise.
|
||||
</p>
|
||||
<p class="flex-shrink-0 pl-4">
|
||||
<a href={base + 'about/'}>About</a> ·
|
||||
<a href={base + 'well-being/'}>Well being</a> ·
|
||||
<a href={base + 'imprint/'}>Imprint</a> ·
|
||||
<a href={base + 'privacy-policy/'}>Privacy Policy</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,31 +0,0 @@
|
|||
---
|
||||
import Layout from '@layouts/Layout.astro';
|
||||
|
||||
interface Props {
|
||||
frontmatter: {
|
||||
title?: string;
|
||||
};
|
||||
headings: {
|
||||
depth: number;
|
||||
text: string;
|
||||
slug: string;
|
||||
}[];
|
||||
}
|
||||
const { frontmatter, headings } = Astro.props;
|
||||
let title = frontmatter.title;
|
||||
|
||||
const firstH1 = headings.find((h) => h.depth == 1);
|
||||
|
||||
if (!title && firstH1) {
|
||||
title = firstH1.text;
|
||||
}
|
||||
---
|
||||
|
||||
<Layout title={title}>
|
||||
<main class="flex-auto">
|
||||
<section class="centered-content prose lg:prose-xl py-12">
|
||||
{!firstH1 && frontmatter.title && <h1>{frontmatter.title}</h1>}
|
||||
<slot />
|
||||
</section>
|
||||
</main>
|
||||
</Layout>
|
17
src/layouts/PageLayout.astro
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
import Layout from '~/layouts/BaseLayout.astro';
|
||||
import Header from '~/components/widgets/Header.astro';
|
||||
import Footer from '~/components/widgets/Footer.astro';
|
||||
import Announcement from '~/components/widgets/Announcement.astro';
|
||||
|
||||
const { meta } = Astro.props;
|
||||
---
|
||||
|
||||
<Layout {meta}>
|
||||
<Announcement />
|
||||
<Header />
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
<Footer />
|
||||
</Layout>
|
|
@ -1,23 +0,0 @@
|
|||
import type { Plugin } from 'unified';
|
||||
import type { Root, Link } from 'mdast';
|
||||
|
||||
import { visit } from 'unist-util-visit';
|
||||
|
||||
/**
|
||||
* A remark plugin to prefix the URLs starting with "/" with a base.
|
||||
*/
|
||||
const prefixwithBase: Plugin<[String], Root> = function (base: String) {
|
||||
if (base.endsWith('/')) {
|
||||
base = base.substring(0, base.length - 1);
|
||||
}
|
||||
return (tree) => {
|
||||
visit(tree, 'link', (node: Link) => {
|
||||
if (!node.url || !node.url.startsWith('/')) {
|
||||
return;
|
||||
}
|
||||
node.url = base + node.url;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export default prefixwithBase;
|
|
@ -1,12 +1,11 @@
|
|||
---
|
||||
import Layout from '@layouts/Layout.astro';
|
||||
import Layout from '~/layouts/BaseLayout.astro';
|
||||
import { SITE } from '~/config.mjs';
|
||||
import Error404 from '~/components/widgets/Error404.astro';
|
||||
|
||||
const title = `Error 404 — ${SITE.name}`;
|
||||
---
|
||||
|
||||
<Layout title="Page not found">
|
||||
<main class="flex-auto">
|
||||
<section class="centered-content text-center">
|
||||
<h1 class="py-10 text-6xl">Page not found</h1>
|
||||
<p>Error 404</p>
|
||||
</section>
|
||||
</main>
|
||||
<Layout meta={{ title }}>
|
||||
<Error404 />
|
||||
</Layout>
|
||||
|
|
41
src/pages/[...blog]/[...page].astro
Normal file
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
import { SITE, BLOG } from '~/config.mjs';
|
||||
|
||||
import Layout from '~/layouts/BlogLayout.astro';
|
||||
import BlogList from '~/components/blog/List.astro';
|
||||
import Pagination from '~/components/atoms/Pagination.astro';
|
||||
|
||||
import { fetchPosts } from '~/utils/posts';
|
||||
import { getCanonical, getPermalink, BLOG_BASE } from '~/utils/permalinks';
|
||||
|
||||
export async function getStaticPaths({ paginate }) {
|
||||
if (BLOG?.disabled || BLOG?.blog?.disabled) return [];
|
||||
|
||||
const posts = await fetchPosts();
|
||||
|
||||
return paginate(posts, {
|
||||
params: { blog: BLOG_BASE || undefined },
|
||||
pageSize: BLOG.postsPerPage,
|
||||
});
|
||||
}
|
||||
|
||||
const { page } = Astro.props;
|
||||
const currentPage = page.currentPage ?? 1;
|
||||
|
||||
const meta = {
|
||||
title: `Blog ${currentPage > 1 ? `— Page ${currentPage} ` : ''}— ${SITE.name}`,
|
||||
description: SITE.description,
|
||||
canonical: getCanonical(getPermalink(BLOG?.blog?.pathname)),
|
||||
ogType: 'blog',
|
||||
noindex: currentPage > 1,
|
||||
};
|
||||
---
|
||||
|
||||
<Layout {meta}>
|
||||
<Fragment slot="title">
|
||||
News and tutorials about
|
||||
<span>AstroWind</span>
|
||||
</Fragment>
|
||||
<BlogList posts={page.data} />
|
||||
<Pagination prevUrl={page.url.prev} nextUrl={page.url.next} />
|
||||
</Layout>
|
40
src/pages/[...blog]/[slug].astro
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
import { SITE, BLOG } from '~/config.mjs';
|
||||
|
||||
import Layout from '~/layouts/PageLayout.astro';
|
||||
import SinglePost from '~/components/blog/SinglePost.astro';
|
||||
|
||||
import { getCanonical, getPermalink, cleanSlug, POST_BASE } from '~/utils/permalinks';
|
||||
import { fetchPosts } from '~/utils/posts';
|
||||
import { findImage } from '~/utils/images';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
if (BLOG?.disabled || BLOG?.post?.disabled) return [];
|
||||
|
||||
const posts = await fetchPosts();
|
||||
|
||||
return posts.map((post) => ({
|
||||
params: {
|
||||
slug: cleanSlug(post.slug),
|
||||
blog: POST_BASE || undefined,
|
||||
},
|
||||
props: { post },
|
||||
}));
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
const url = getCanonical(getPermalink(post.slug, 'post'));
|
||||
|
||||
const meta = {
|
||||
title: `${post.title} — ${SITE.name}`,
|
||||
description: post.description,
|
||||
canonical: post.canonical || url,
|
||||
image: await findImage(post.image),
|
||||
ogTitle: post.title,
|
||||
ogType: 'article',
|
||||
};
|
||||
---
|
||||
|
||||
<Layout {meta}>
|
||||
<SinglePost post={{ ...post, image: meta.image }} url={url} />
|
||||
</Layout>
|
51
src/pages/[...categories]/[category]/[...page].astro
Normal file
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
import { SITE, BLOG } from '~/config.mjs';
|
||||
|
||||
import Layout from '~/layouts/BlogLayout.astro';
|
||||
import BlogList from '~/components/blog/List.astro';
|
||||
import Pagination from '~/components/atoms/Pagination.astro';
|
||||
|
||||
import { fetchPosts } from '~/utils/posts';
|
||||
import { getCanonical, getPermalink, cleanSlug, CATEGORY_BASE } from '~/utils/permalinks';
|
||||
|
||||
export async function getStaticPaths({ paginate }) {
|
||||
if (BLOG?.disabled || BLOG?.category?.disabled) return [];
|
||||
|
||||
const posts = await fetchPosts();
|
||||
|
||||
const categories = new Set();
|
||||
posts.map((post) => {
|
||||
typeof post.category === 'string' && categories.add(post.category.toLowerCase());
|
||||
});
|
||||
|
||||
return Array.from(categories).map((category) =>
|
||||
paginate(
|
||||
posts.filter((post) => typeof post.category === 'string' && category === post.category.toLowerCase()),
|
||||
{
|
||||
params: { category: cleanSlug(category), categories: CATEGORY_BASE || undefined },
|
||||
pageSize: BLOG.postsPerPage,
|
||||
props: { category },
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const { page, category } = Astro.props;
|
||||
|
||||
const currentPage = page.currentPage ?? 1;
|
||||
|
||||
const meta = {
|
||||
title: `Category '${category}' ${currentPage > 1 ? `— Page ${currentPage} ` : ''}— ${SITE.name}`,
|
||||
description: SITE.description,
|
||||
canonical: getCanonical(getPermalink(category, 'category')),
|
||||
noindex: true,
|
||||
};
|
||||
---
|
||||
|
||||
<Layout meta={meta}>
|
||||
<Fragment slot="title">
|
||||
Category: {category}
|
||||
</Fragment>
|
||||
<BlogList posts={page.data} />
|
||||
<Pagination prevUrl={page.url.prev} nextUrl={page.url.next} />
|
||||
</Layout>
|
51
src/pages/[...tags]/[tag]/[...page].astro
Normal file
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
import { SITE, BLOG } from '~/config.mjs';
|
||||
|
||||
import Layout from '~/layouts/BlogLayout.astro';
|
||||
import BlogList from '~/components/blog/List.astro';
|
||||
import Pagination from '~/components/atoms/Pagination.astro';
|
||||
|
||||
import { fetchPosts } from '~/utils/posts';
|
||||
import { getCanonical, getPermalink, cleanSlug, TAG_BASE } from '~/utils/permalinks';
|
||||
|
||||
export async function getStaticPaths({ paginate }) {
|
||||
if (BLOG?.disabled || BLOG?.tag?.disabled) return [];
|
||||
|
||||
const posts = await fetchPosts();
|
||||
|
||||
const tags = new Set();
|
||||
posts.map((post) => {
|
||||
Array.isArray(post.tags) && post.tags.map((tag) => tags.add(tag.toLowerCase()));
|
||||
});
|
||||
|
||||
return Array.from(tags).map((tag) =>
|
||||
paginate(
|
||||
posts.filter((post) => Array.isArray(post.tags) && post.tags.includes(tag)),
|
||||
{
|
||||
params: { tag: cleanSlug(tag), tags: TAG_BASE || undefined },
|
||||
pageSize: BLOG.postsPerPage,
|
||||
props: { tag },
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const { page, tag } = Astro.props;
|
||||
|
||||
const currentPage = page.currentPage ?? 1;
|
||||
|
||||
const meta = {
|
||||
title: `Posts by tag '${tag}' ${currentPage > 1 ? `— Page ${currentPage} ` : ''}— ${SITE.name}`,
|
||||
description: SITE.description,
|
||||
canonical: getCanonical(getPermalink(tag, 'tag')),
|
||||
noindex: true,
|
||||
};
|
||||
---
|
||||
|
||||
<Layout meta={meta}>
|
||||
<Fragment slot="title">
|
||||
Tag: {tag}
|
||||
</Fragment>
|
||||
<BlogList posts={page.data} />
|
||||
<Pagination prevUrl={page.url.prev} nextUrl={page.url.next} />
|
||||
</Layout>
|
|
@ -1,39 +1,35 @@
|
|||
---
|
||||
import Layout from '@layouts/Layout.astro';
|
||||
import { SITE } from '~/config.mjs';
|
||||
import { getCanonical, getHomePermalink } from '~/utils/permalinks';
|
||||
import Layout from '~/layouts/PageLayout.astro';
|
||||
|
||||
import Hero from '~/components/widgets/Hero.astro';
|
||||
import Note from '~/components/widgets/Note.astro';
|
||||
import Features from '~/components/widgets/Features.astro';
|
||||
import Features2 from '~/components/widgets/Features2.astro';
|
||||
import Steps from '~/components/widgets/Steps.astro';
|
||||
import Features3 from '~/components/widgets/Features3.astro';
|
||||
import HighlightedPosts from '~/components/blog/HighlightedPosts.astro';
|
||||
import FAQs from '~/components/widgets/FAQs.astro';
|
||||
import Stats from '~/components/widgets/Stats.astro';
|
||||
import CallToAction from '~/components/widgets/CallToAction.astro';
|
||||
|
||||
const meta = {
|
||||
title: SITE.title,
|
||||
description: SITE.description,
|
||||
canonical: getCanonical(getHomePermalink()),
|
||||
};
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<main class="flex-auto">
|
||||
<section class="bg-gradient-to-b from-purple-900 to-pink-400 text-white text-opacity-75">
|
||||
<div class="centered-content py-20">
|
||||
<h1 class="pt-10 text-6xl">Forgejo - Beyond coding. We forge.</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section class="centered-content py-10">
|
||||
<h2 class="text-2xl pb-10">What is Forgejo?</h2>
|
||||
<p>
|
||||
Forgejo is a self-hosted lightweight software forge, easy to install and low maintenance that just does the job. Brought to you by an inclusive community under the umbrella of <a href="https://docs.codeberg.org/getting-started/what-is-codeberg/#what-is-codeberg-e.v.%3F">Codeberg e.V.</a> a democratic non-profit organization, Forgejo can be trusted to be exclusively Free Software. It is a "soft" fork of Gitea with a focus on scaling, federation and privacy.
|
||||
</p>
|
||||
<h2 class="text-2xl pb-10">Get Forgejo</h2>
|
||||
<p>
|
||||
Binary for amd64 or <a href="https://codeberg.org/forgejo/forgejo/releases">other architectures</a>.
|
||||
<ul>
|
||||
<li>wget -O forgejo-1.18.0-rc0 https://codeberg.org/attachments/071b3f92-0b6b-45a3-aa3a-6c11ae7fc91e && chmod +x forgejo-1.18.0-rc0</li>
|
||||
<li>gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710</li>
|
||||
<li>wget -O forgejo-1.18.0-rc0.asc https://codeberg.org/attachments/06e0720d-4357-4516-9484-2d7c36673870</li>
|
||||
<li>gpg --verify forgejo-1.18.0-rc0.asc forgejo-1.18.0-rc0</li>
|
||||
</ul>
|
||||
<p>
|
||||
</p>
|
||||
<a href="https://codeberg.org/forgejo/-/packages/container/forgejo/versions">Container image</a>.
|
||||
<ul>
|
||||
<li>docker pull codeberg.org/forgejo/forgejo:1.18.0-rc0</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h2 class="text-2xl pb-10">Get involved</h2>
|
||||
<p>
|
||||
Forgejo consists of motivated people, and we are looking forward to <a href="https://codeberg.org/forgejo/forgejo/src/branch/forgejo/CONTRIBUTING.md">your contribution</a>. Feel free to help in the domains of <a href="https://codeberg.org/forgejo/forgejo/issues">code, federation, releases management</a>, User Research, UX, <a href="https://codeberg.org/forgejo/code-of-conduct/issues">community management</a>, documentation, web design, <a href="https://codeberg.org/forgejo/meta/issues">governance</a> and more.
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
<Layout {meta}>
|
||||
<Hero />
|
||||
<Note />
|
||||
<Features />
|
||||
<Steps />
|
||||
<Features2 />
|
||||
<Features3 />
|
||||
<HighlightedPosts />
|
||||
<FAQs />
|
||||
<Stats />
|
||||
<CallToAction />
|
||||
</Layout>
|
||||
|
|
29
src/pages/rss.xml.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import rss from '@astrojs/rss';
|
||||
|
||||
import { SITE, BLOG } from '~/config.mjs';
|
||||
import { fetchPosts } from '~/utils/posts';
|
||||
import { getPermalink } from '~/utils/permalinks';
|
||||
|
||||
export const get = async () => {
|
||||
if (BLOG.disabled) {
|
||||
return new Response(null, {
|
||||
status: 404,
|
||||
statusText: 'Not found',
|
||||
});
|
||||
}
|
||||
|
||||
const posts = await fetchPosts();
|
||||
|
||||
return rss({
|
||||
title: `${SITE.name}’s Blog`,
|
||||
description: SITE.description,
|
||||
site: import.meta.env.SITE,
|
||||
|
||||
items: posts.map((post) => ({
|
||||
link: getPermalink(post.slug, 'post'),
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
publishDate: post.publishDate,
|
||||
})),
|
||||
});
|
||||
};
|
|
@ -1,16 +0,0 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer components {
|
||||
/* own classes */
|
||||
.centered-content {
|
||||
@apply max-w-6xl mx-auto px-4 sm:px-6;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
a {
|
||||
@apply underline;
|
||||
}
|
||||
}
|
22
src/utils/directories.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/** */
|
||||
export const getProjectRootDir = () => {
|
||||
const mode = import.meta.env.MODE;
|
||||
|
||||
return mode === 'production' ? path.join(__dirname, '../') : path.join(__dirname, '../../');
|
||||
};
|
||||
|
||||
const __srcFolder = path.join(getProjectRootDir(), '/src');
|
||||
|
||||
/** */
|
||||
export const getRelativeUrlByFilePath = (filepath) => {
|
||||
if (filepath) {
|
||||
return filepath.replace(__srcFolder, '');
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
11
src/utils/frontmatter.mjs
Normal file
|
@ -0,0 +1,11 @@
|
|||
import getReadingTime from 'reading-time';
|
||||
import { toString } from 'mdast-util-to-string';
|
||||
|
||||
export function remarkReadingTime() {
|
||||
return function (tree, { data }) {
|
||||
const text = toString(tree);
|
||||
const readingTime = Math.ceil(getReadingTime(text).minutes);
|
||||
|
||||
data.astro.frontmatter.readingTime = readingTime;
|
||||
};
|
||||
}
|
37
src/utils/images.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
const load = async function () {
|
||||
let images = [];
|
||||
try {
|
||||
images = import.meta.glob('~/assets/images/**');
|
||||
} catch (e) {
|
||||
// continue regardless of error
|
||||
}
|
||||
return images;
|
||||
};
|
||||
|
||||
let _images;
|
||||
|
||||
/** */
|
||||
export const fetchLocalImages = async () => {
|
||||
_images = _images || load();
|
||||
return await _images;
|
||||
};
|
||||
|
||||
/** */
|
||||
export const findImage = async (imagePath) => {
|
||||
if (typeof imagePath !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {
|
||||
return imagePath;
|
||||
}
|
||||
|
||||
if (!imagePath.startsWith('~/assets')) {
|
||||
return null;
|
||||
} // For now only consume images using ~/assets alias (or absolute)
|
||||
|
||||
const images = await fetchLocalImages();
|
||||
const key = imagePath.replace('~/', '/src/');
|
||||
|
||||
return typeof images[key] === 'function' ? (await images[key]())['default'] : null;
|
||||
};
|
63
src/utils/permalinks.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
import slugify from 'limax';
|
||||
|
||||
import { SITE, BLOG } from '~/config.mjs';
|
||||
|
||||
const trim = (str, ch) => {
|
||||
let start = 0,
|
||||
end = str.length || 0;
|
||||
while (start < end && str[start] === ch) ++start;
|
||||
while (end > start && str[end - 1] === ch) --end;
|
||||
return start > 0 || end < str.length ? str.substring(start, end) : str;
|
||||
};
|
||||
|
||||
const trimSlash = (s) => trim(trim(s, '/'));
|
||||
const createPath = (...params) => {
|
||||
const paths = params.filter((el) => !!el).join('/');
|
||||
return '/' + paths + (SITE.trailingSlash && paths ? '/' : '');
|
||||
};
|
||||
|
||||
const basePathname = trimSlash(SITE.basePathname);
|
||||
|
||||
export const cleanSlug = (text) => slugify(trimSlash(text));
|
||||
|
||||
export const BLOG_BASE = cleanSlug(BLOG?.blog?.pathname);
|
||||
export const POST_BASE = cleanSlug(BLOG?.post?.pathname);
|
||||
export const CATEGORY_BASE = cleanSlug(BLOG?.category?.pathname);
|
||||
export const TAG_BASE = cleanSlug(BLOG?.tag?.pathname);
|
||||
|
||||
/** */
|
||||
export const getCanonical = (path = '') => new URL(path, SITE.origin);
|
||||
|
||||
/** */
|
||||
export const getPermalink = (slug = '', type = 'page') => {
|
||||
const _slug = cleanSlug(slug);
|
||||
|
||||
switch (type) {
|
||||
case 'category':
|
||||
return createPath(basePathname, CATEGORY_BASE, _slug);
|
||||
|
||||
case 'tag':
|
||||
return createPath(basePathname, TAG_BASE, _slug);
|
||||
|
||||
case 'post':
|
||||
return createPath(basePathname, POST_BASE, _slug);
|
||||
|
||||
case 'page':
|
||||
default:
|
||||
return createPath(basePathname, _slug);
|
||||
}
|
||||
};
|
||||
|
||||
/** */
|
||||
export const getHomePermalink = () => {
|
||||
const permalink = getPermalink();
|
||||
return permalink !== '/' ? permalink + '/' : permalink;
|
||||
};
|
||||
|
||||
/** */
|
||||
export const getRelativeLink = (link = "") => {
|
||||
return createPath(basePathname, trimSlash(link));
|
||||
}
|
||||
|
||||
/** */
|
||||
export const getBlogPermalink = () => getPermalink(BLOG_BASE);
|
74
src/utils/posts.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
const getNormalizedPost = async (post) => {
|
||||
const { frontmatter, Content, file } = post;
|
||||
const ID = file.split('/').pop().split('.').shift();
|
||||
|
||||
return {
|
||||
id: ID,
|
||||
|
||||
publishDate: frontmatter.publishDate,
|
||||
draft: frontmatter.draft,
|
||||
|
||||
canonical: frontmatter.canonical,
|
||||
slug: frontmatter.slug || ID,
|
||||
|
||||
title: frontmatter.title,
|
||||
description: frontmatter.description,
|
||||
image: frontmatter.image,
|
||||
|
||||
Content: Content,
|
||||
// or 'body' in case you consume from API
|
||||
|
||||
excerpt: frontmatter.excerpt,
|
||||
authors: frontmatter.authors,
|
||||
category: frontmatter.category,
|
||||
tags: frontmatter.tags,
|
||||
readingTime: frontmatter.readingTime,
|
||||
};
|
||||
};
|
||||
|
||||
const load = async function () {
|
||||
const posts = import.meta.glob(['~/../data/blog/**/*.md', '~/../data/blog/**/*.mdx'], {
|
||||
eager: true,
|
||||
});
|
||||
|
||||
const normalizedPosts = Object.keys(posts).map(async (key) => {
|
||||
const post = await posts[key];
|
||||
return await getNormalizedPost(post);
|
||||
});
|
||||
|
||||
const results = (await Promise.all(normalizedPosts))
|
||||
.sort((a, b) => new Date(b.publishDate).valueOf() - new Date(a.publishDate).valueOf())
|
||||
.filter((post) => !post.draft);
|
||||
return results;
|
||||
};
|
||||
|
||||
let _posts;
|
||||
|
||||
/** */
|
||||
export const fetchPosts = async () => {
|
||||
_posts = _posts || load();
|
||||
|
||||
return await _posts;
|
||||
};
|
||||
|
||||
/** */
|
||||
export const findPostsByIds = async (ids) => {
|
||||
if (!Array.isArray(ids)) return [];
|
||||
|
||||
const posts = await fetchPosts();
|
||||
|
||||
return ids.reduce(function (r, id) {
|
||||
posts.some(function (post) {
|
||||
return id === post.id && r.push(post);
|
||||
});
|
||||
return r;
|
||||
}, []);
|
||||
};
|
||||
|
||||
/** */
|
||||
export const findLatestPosts = async ({ count }) => {
|
||||
const _count = count || 4;
|
||||
const posts = await fetchPosts();
|
||||
|
||||
return posts ? posts.slice(_count * -1) : [];
|
||||
};
|
9
src/utils/utils.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
/** */
|
||||
export const getFormattedDate = (date) =>
|
||||
date
|
||||
? new Date(date).toLocaleDateString('en-us', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})
|
||||
: '';
|
|
@ -1,8 +1,44 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
const defaultTheme = require('tailwindcss/defaultTheme');
|
||||
const colors = require('tailwindcss/colors');
|
||||
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
extend: {
|
||||
colors: {
|
||||
primary: colors.blue,
|
||||
secondary: colors.pink,
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ["'InterVariable'", ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require('@tailwindcss/typography')],
|
||||
darkMode: 'class',
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Alternative tailwind.config.js
|
||||
|
||||
NOTE: Add this fonts to <head>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;700&display=swap" rel="stylesheet" />
|
||||
*/
|
||||
|
||||
// module.exports = {
|
||||
// content: ["./src/**/*.{astro,html,js,jsx,md,svelte,ts,tsx,vue}"],
|
||||
// theme: {
|
||||
// extend: {
|
||||
// colors: {
|
||||
// primary: colors.cyan,
|
||||
// secondary: colors.lime,
|
||||
// },
|
||||
// fontFamily: {
|
||||
// sans: ["'Nunito'", ...defaultTheme.fontFamily.sans],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// plugins: [require("@tailwindcss/typography")],
|
||||
// darkMode: "class",
|
||||
// };
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"extends": "astro/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"types": ["astro/client"],
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@components/*": ["src/components/*"],
|
||||
"@layouts/*": ["src/layouts/*"]
|
||||
"~/*": ["src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
vercel.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"cleanUrls": true,
|
||||
"trailingSlash": false,
|
||||
"headers": [
|
||||
{
|
||||
"source": "/assets/(.*)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "public, max-age=31536000, immutable"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|